From 7100b90e71e56ee4f4b5eca32f8bc3f305725833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E5=90=8DTomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Mon, 1 Dec 2025 22:05:54 +0800 Subject: [PATCH 01/45] fix: replace missing transparent-bg.png with css pattern --- src/components/Tools/GifCompress/GifCompress.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/Tools/GifCompress/GifCompress.vue b/src/components/Tools/GifCompress/GifCompress.vue index 1f8c3a4..c4beecf 100644 --- a/src/components/Tools/GifCompress/GifCompress.vue +++ b/src/components/Tools/GifCompress/GifCompress.vue @@ -193,15 +193,15 @@
原始图片
{{ originalDimensions.width - }}x{{ originalDimensions.height }} + }}x{{ originalDimensions.height }} {{ formatSize(originalSize) }}
-
+
@@ -225,12 +225,12 @@
{{ customDimensions.width - }}x{{ customDimensions.height }} + }}x{{ customDimensions.height }} {{ formatSize(compressedSize) - }} + }} -{{ calculateReduction() - }}% + }}%
Date: Wed, 3 Dec 2025 11:41:29 +0800 Subject: [PATCH 02/45] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E9=85=8D=E9=9F=B3=E5=B7=A5=E5=85=B7=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96PromptReverse=E5=8F=8A=E6=9B=B4=E6=96=B0=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Home/Changelog.vue | 157 ++- src/components/Tools/AI/PromptReverse.vue | 350 ++++++ src/components/Tools/AI/TextToSpeech.vue | 270 ++++ src/components/Tools/Design/IconGenerator.vue | 1101 +++++++++-------- src/components/Tools/Horoscope/Horoscope.vue | 1068 ++++++---------- src/components/Tools/icons.ts | 8 + src/components/Tools/tools.ts | 22 + src/router/router.ts | 20 + ssr.config.ts | 3 +- 9 files changed, 1786 insertions(+), 1213 deletions(-) create mode 100644 src/components/Tools/AI/PromptReverse.vue create mode 100644 src/components/Tools/AI/TextToSpeech.vue diff --git a/src/components/Home/Changelog.vue b/src/components/Home/Changelog.vue index eb8ac3c..1e1affb 100644 --- a/src/components/Home/Changelog.vue +++ b/src/components/Home/Changelog.vue @@ -12,9 +12,9 @@ import { ref, onMounted, onUnmounted, watch, type ComponentPublicInstance } from * * @author Tomda * @createDate 2025-01-09 - * @lastUpdate 2025-12-01 14:30 - * @version Beta 2.2.8 - * @toolsCount 当前工具总数:88个 + * @lastUpdate 2025-12-03 10:00 + * @version Beta 2.3.2 + * @toolsCount 当前工具总数:90个 */ const tocItems = ref<{ id: string; version: string; date: string; title: string }[]>([]); @@ -243,7 +243,7 @@ onUnmounted(() => {
- 当前工具总数:88个 | 最后更新:2025-12-01 10:00 + 当前工具总数:90个 | 最后更新:2025-12-03 10:00
@@ -280,6 +280,155 @@ onUnmounted(() => {
+ +
+
+ 2.3.2 + 2025-12-03 10:00 +
+
+
+ 新增 + 免费在线文本配音工具上线 +
+
+
    +
  • +
    文本转语音功能
    +
    +
      +
    • 支持多种角色声音选择(少女音、阳光男声、成熟女声等)
    • +
    • 提供丰富的情感风格(愉快、悲伤、严肃等)
    • +
    • 一键生成自然流畅的语音,支持在线试听与下载
    • + 立即体验 → +
    +
    +
  • +
  • +
    功能优化
    +
    +
      +
    • 图片提示词反推工具:优化UI设计,精简模型选择,提升反推体验
    • +
    +
    +
  • +
+
+
+
+ + +
+
+ 2.3.1 + 2025-12-02 16:00 +
+
+
+ 新增 + 免费图片提示词反推工具上线 +
+
+
    +
  • +
    核心功能
    +
    +
      +
    • 支持图片上传与URL输入反推提示词
    • +
    • 通用模型精准识别,中文结果输出
    • +
    • 一键复制反推结果,便捷高效
    • +
    +
    +
  • + 立即体验 → +
+
+
+
+ + +
+
+ 2.3.0 + 2025-12-02 15:30 +
+
+
+ 重磅 + 星座运势工具全新升级 +
+
+
    +
  • +
    视觉与交互重构
    +
    +
      +
    • 全新 深空主题UI,融合毛玻璃拟态设计,沉浸感十足
    • +
    • 新增 横向滚动星座选择器,配合流畅动效,切换更丝滑
    • +
    • 重构 响应式网格布局,完美适配移动端与桌面端显示
    • +
    +
    +
  • +
  • +
    功能与体验优化
    +
    +
      +
    • 新增 文案完整性智能检测,自动处理截断问题,确保内容完整
    • +
    • 优化 分享卡片生成算法,支持动态高度与高清渲染
    • +
    • 集成 SEO 结构化数据 与语义化文件名,提升搜索可见性
    • + 立即体验 → +
    +
    +
  • +
+
+
+
+ + +
+
+ 2.2.9 + 2025-12-02 11:00 +
+
+
+ 重磅 + 免费应用图标生成器全新升级 +
+
+
    +
  • +
    核心功能增强
    +
    +
      +
    • 支持 多格式导出 (PNG/SVG/ICO),满足全平台开发需求
    • +
    • 新增 自定义尺寸设置 (16x16 至 1024x1024),灵活适配各种场景
    • +
    • 支持 实时预览多图层编辑,设计效果所见即所得
    • +
    • 内置 多平台预设 (iOS/Android/Web),一键生成标准图标包
    • + 立即体验 → +
    +
    +
  • +
  • +
    性能与体验优化
    +
    +
      +
    • 采用 异步渲染引擎智能缓存机制,操作流畅无卡顿
    • +
    • 全新 响应式布局,完美适配移动端与桌面端操作
    • +
    • 纯前端处理,数据不上传,完全保护用户隐私
    • +
    +
    +
  • +
+
+
+
+
diff --git a/src/components/Tools/AI/PromptReverse.vue b/src/components/Tools/AI/PromptReverse.vue new file mode 100644 index 0000000..cee5a53 --- /dev/null +++ b/src/components/Tools/AI/PromptReverse.vue @@ -0,0 +1,350 @@ + + + + + + + diff --git a/src/components/Tools/AI/TextToSpeech.vue b/src/components/Tools/AI/TextToSpeech.vue new file mode 100644 index 0000000..ace7567 --- /dev/null +++ b/src/components/Tools/AI/TextToSpeech.vue @@ -0,0 +1,270 @@ + + + + + + diff --git a/src/components/Tools/Design/IconGenerator.vue b/src/components/Tools/Design/IconGenerator.vue index 8b4bb21..07a8277 100644 --- a/src/components/Tools/Design/IconGenerator.vue +++ b/src/components/Tools/Design/IconGenerator.vue @@ -5,594 +5,656 @@ * @copyright UIED技术团队 (https://fsuied.com) * @author UIED技术团队 * @createDate 2025-01-21 - * - * 功能特性: - * 1. 支持多平台图标生成(iOS、Android、Web App等) - * 2. 支持JPG、PNG、PSD等多种格式上传 - * 3. 支持自定义圆角和大小设置 - * 4. 支持实时预览效果 - * 5. 支持批量导出不同尺寸 - * 6. 自动优化小尺寸图标清晰度 + * @lastUpdate 2025-01-23 --> - - diff --git a/src/components/Tools/Horoscope/Horoscope.vue b/src/components/Tools/Horoscope/Horoscope.vue index 5f8ea35..52eb807 100644 --- a/src/components/Tools/Horoscope/Horoscope.vue +++ b/src/components/Tools/Horoscope/Horoscope.vue @@ -1,403 +1,308 @@ -/** -* @file Horoscope.vue -* @description 星座运势工具,支持多时段运势查询和运势卡片生成 -* -* @copyright Tomda (https://www.tomda.top) -* @copyright UIED技术团队 (https://fsuied.com) -* @copyright 2024-2025 All Rights Reserved. -* -* @author Tomda -* @createDate 2025-01-28 -* @lastUpdate 2025-01-28 22:58 -* @version Beta 1.0.9 -* @toolsCount 当前工具总数:61个 -* -* @features -* - 支持多时段运势查询(今日/明日/本周/本月) -* - 支持运势卡片生成与分享功能 -* - 支持二维码快速访问 -* - 优雅的响应式布局设计 -* - 实时获取最新星座运势数据 -* - 支持一键生成运势卡片 -* - 支持复制和下载运势卡片 -* - 优雅的动画和交互效果 -*/ - @@ -429,63 +334,51 @@ interface Fortune { healthtxt: string } -interface FortuneResponse { - code: number - msg: string - xz: string - data: Fortune - api_source: string -} - // 星座数据 const zodiacs = [ - { name: '白羊', icon: '♈️', type: 'aries', dateRange: '3月21日-4月19日' }, - { name: '金牛', icon: '♉️', type: 'taurus', dateRange: '4月20日-5月20日' }, - { name: '双子', icon: '♊️', type: 'gemini', dateRange: '5月21日-6月21日' }, - { name: '巨蟹', icon: '♋️', type: 'cancer', dateRange: '6月22日-7月22日' }, - { name: '狮子', icon: '♌️', type: 'leo', dateRange: '7月23日-8月22日' }, - { name: '处女', icon: '♍️', type: 'virgo', dateRange: '8月23日-9月22日' }, - { name: '天秤', icon: '♎️', type: 'libra', dateRange: '9月23日-10月23日' }, - { name: '天蝎', icon: '♏️', type: 'scorpio', dateRange: '10月24日-11月22日' }, - { name: '射手', icon: '♐️', type: 'sagittarius', dateRange: '11月23日-12月21日' }, - { name: '摩羯', icon: '♑️', type: 'capricorn', dateRange: '12月22日-1月19日' }, - { name: '水瓶', icon: '♒️', type: 'aquarius', dateRange: '1月20日-2月18日' }, - { name: '双鱼', icon: '♓️', type: 'pisces', dateRange: '2月19日-3月20日' } + { name: '白羊', icon: '♈️', type: 'aries', dateRange: '3.21-4.19' }, + { name: '金牛', icon: '♉️', type: 'taurus', dateRange: '4.20-5.20' }, + { name: '双子', icon: '♊️', type: 'gemini', dateRange: '5.21-6.21' }, + { name: '巨蟹', icon: '♋️', type: 'cancer', dateRange: '6.22-7.22' }, + { name: '狮子', icon: '♌️', type: 'leo', dateRange: '7.23-8.22' }, + { name: '处女', icon: '♍️', type: 'virgo', dateRange: '8.23-9.22' }, + { name: '天秤', icon: '♎️', type: 'libra', dateRange: '9.23-10.23' }, + { name: '天蝎', icon: '♏️', type: 'scorpio', dateRange: '10.24-11.22' }, + { name: '射手', icon: '♐️', type: 'sagittarius', dateRange: '11.23-12.21' }, + { name: '摩羯', icon: '♑️', type: 'capricorn', dateRange: '12.22-1.19' }, + { name: '水瓶', icon: '♒️', type: 'aquarius', dateRange: '1.20-2.18' }, + { name: '双鱼', icon: '♓️', type: 'pisces', dateRange: '2.19-3.20' } ] -// 运势标签 -const fortuneLabels = { - all: '综合', - love: '爱情', - work: '事业', - money: '财运', - health: '健康' -} - // 状态管理 const selectedZodiac = ref('白羊') const fortune: Ref = ref(null) const loading = ref(false) const error = ref('') const route = useRoute() -const showQRCode = ref(false) const showPreview = ref(false) const previewImage = ref('') const isGenerating = ref(false) +const captureRef = ref() +const qrCodeRef = ref() +const zodiacScroll = ref() // 计算当前选中的星座信息 const selectedZodiacInfo = computed(() => { return zodiacs.find(z => z.name === selectedZodiac.value) }) -// 运势图标 -const fortuneIcons = { - all: '🌟', - love: '💝', - work: '💼', - money: '💰', - health: '💪' -} +// 显示卡片数据处理 +const displayCards = computed(() => { + if (!fortune.value) return [] + return [ + // 过滤掉综合运势,因为它已经单独显示了,或者保留但换个样式 + { key: 'love', label: '爱情运势', icon: '💝', text: fortune.value.lovetext }, + { key: 'work', label: '事业运势', icon: '💼', text: fortune.value.worktext }, + { key: 'money', label: '财运运势', icon: '💰', text: fortune.value.moneytext }, + { key: 'health', label: '健康运势', icon: '💪', text: fortune.value.healthtxt, score: fortune.value.health } + ] +}) // 幸运指数数据处理 const luckyItems = computed(() => { @@ -498,23 +391,18 @@ const luckyItems = computed(() => { ] }) -// 引用元素 -const captureRef = ref() -const qrCodeRef = ref() - // 生成二维码 const generateQRCode = async () => { if (!qrCodeRef.value) return try { - // 构建完整的 URL const fullUrl = new URL(window.location.pathname, window.location.origin) fullUrl.searchParams.set('zodiac', selectedZodiac.value) await QRCode.toCanvas(qrCodeRef.value, fullUrl.toString(), { - width: 96, - margin: 1, + width: 100, + margin: 0, color: { - dark: '#4F46E5', + dark: '#000000', light: '#FFFFFF' } }) @@ -534,11 +422,10 @@ const generatePreview = async () => { try { isGenerating.value = true - showQRCode.value = true - // 等待 DOM 更新完成 await nextTick() - await new Promise(resolve => setTimeout(resolve, 300)) + // 等待图片和字体加载 + await new Promise(resolve => setTimeout(resolve, 500)) if (!captureRef.value) { throw new Error('截图容器未找到') @@ -549,38 +436,33 @@ const generatePreview = async () => { throw new Error('二维码生成失败') } - await new Promise(resolve => setTimeout(resolve, 200)) + // 确保二维码渲染完成 + await new Promise(resolve => setTimeout(resolve, 100)) + + const dpr = window.devicePixelRatio || 2 - // 获取设备像素比 - const dpr = window.devicePixelRatio || 1 - const scale = Math.max(dpr, 2) // 确保至少2倍缩放 + // 检查文案完整性 + if (fortune.value.lovetext.length > 300 || fortune.value.worktext.length > 300) { + ElMessage.warning('文案较长,生成图片可能较大') + } const canvas = await html2canvas(captureRef.value, { - scale: scale, - backgroundColor: '#ffffff', + scale: dpr, + backgroundColor: '#0f172a', // 强制背景色 logging: false, useCORS: true, allowTaint: true, - width: captureRef.value.offsetWidth, - height: captureRef.value.offsetHeight, - // 优化渲染质量 imageTimeout: 0, - removeContainer: true, - foreignObjectRendering: false + // 确保高度自适应 + height: captureRef.value.offsetHeight, + windowHeight: captureRef.value.scrollHeight }) - // 压缩图片质量 - const maxWidth = 1200 * scale - if (canvas.width > maxWidth) { - const tempCanvas = document.createElement('canvas') - const ctx = tempCanvas.getContext('2d') - const ratio = maxWidth / canvas.width - tempCanvas.width = maxWidth - tempCanvas.height = canvas.height * ratio - ctx?.drawImage(canvas, 0, 0, tempCanvas.width, tempCanvas.height) - previewImage.value = tempCanvas.toDataURL('image/png', 0.9) - } else { - previewImage.value = canvas.toDataURL('image/png', 0.9) + previewImage.value = canvas.toDataURL('image/png', 1.0) + + // 简单的完整性检查:如果生成失败或为空 + if (previewImage.value.length < 1000) { + throw new Error('生成图片异常,请重试') } showPreview.value = true @@ -589,74 +471,49 @@ const generatePreview = async () => { console.error('生成预览失败:', err) ElMessage.error('生成预览失败,请稍后重试') } finally { - showQRCode.value = false isGenerating.value = false } } // 复制图片到剪贴板 const copyImage = async () => { - if (!previewImage.value) { - ElMessage.warning('请先生成预览图片') - return - } - + if (!previewImage.value) return try { - // 从 base64 URL 创建 Blob const response = await fetch(previewImage.value) const blob = await response.blob() - - // 创建 ClipboardItem - const item = new ClipboardItem({ - [blob.type]: blob - }) - - // 复制到剪贴板 + const item = new ClipboardItem({ [blob.type]: blob }) await navigator.clipboard.write([item]) ElMessage.success('图片已复制到剪贴板') } catch (err) { - console.error('复制图片失败:', err) - ElMessage.error('复制图片失败,请尝试使用下载功能') + ElMessage.error('复制失败,请尝试保存图片') } } // 下载图片 const downloadImage = () => { - if (!previewImage.value) { - ElMessage.warning('请先生成预览图片') - return - } - + if (!previewImage.value) return const link = document.createElement('a') - link.download = `${selectedZodiac.value}座-今日运势.png` + const dateStr = new Date().toISOString().split('T')[0] + // 语义化命名:产品名称-功能-规格(时间).png + link.download = `UIED工具-星座运势-${selectedZodiac.value}-${dateStr}.png` link.href = previewImage.value link.click() - - ElMessage.success('运势卡片已保存') - showPreview.value = false + ElMessage.success('图片已开始下载') } // 获取运势数据 const getFortune = async () => { loading.value = true error.value = '' - fortune.value = null + // fortune.value = null // 不清空旧数据,避免闪烁 try { const response = await axios.get(`https://api.pearktrue.cn/api/xzys/`, { - params: { - xz: selectedZodiac.value - } + params: { xz: selectedZodiac.value } }) if (response.data.code === 200) { fortune.value = response.data.data - // 添加小动效 - ElMessage({ - message: `已获取${selectedZodiac.value}座今日运势`, - type: 'success', - duration: 2000 - }) } else { throw new Error(response.data.msg || '获取运势数据失败') } @@ -676,278 +533,155 @@ watch(selectedZodiac, () => { getFortune() }) -// 组件加载时获取数据 +// 组件加载时 onMounted(() => { - getFortune() -}) - -// 不需要在路由变化时更新二维码 -watch(() => route.fullPath, () => { - // 移除自动生成二维码的逻辑 -}) - -// 添加一些动画效果 -const addAnimationClass = (value: string, className: string) => { - const element = document.querySelector(value) - if (element) { - element.classList.add(className) - setTimeout(() => { - element.classList.remove(className) - }, 1000) + // 检查 URL 参数 + const urlParams = new URLSearchParams(window.location.search) + const zodiacParam = urlParams.get('zodiac') + if (zodiacParam && zodiacs.some(z => z.name === zodiacParam)) { + selectedZodiac.value = zodiacParam } -} -// SEO优化 - 计算页面标题和描述 -const pageTitle = computed(() => { - return `${selectedZodiac.value}座运势查询_今日运势详解_星座运程分析` + getFortune() }) +// SEO优化 +const pageTitle = computed(() => `${selectedZodiac.value}座今日运势查询 - 星座运程详解`) const pageDescription = computed(() => { if (fortune.value) { - return `${selectedZodiac.value}座今日运势:${fortune.value.shortcomment}。提供${selectedZodiac.value}座的爱情、事业、财运、健康运势分析。` + return `${selectedZodiac.value}座今日运势:${fortune.value.shortcomment}。提供爱情、事业、财运、健康全方位解析。` } - return `免费在线查询${selectedZodiac.value}座今日运势,提供准确的运势预测、爱情运、事业运、财运、健康运势分析,星座运程每日更新。` + return `免费在线查询${selectedZodiac.value}座今日运势,提供准确的运势预测。` }) -// SEO优化 - 结构化数据 -const structuredData = computed(() => { - return { - '@context': 'https://schema.org', - '@type': 'WebPage', - name: pageTitle.value, - description: pageDescription.value, - datePublished: new Date().toISOString(), - dateModified: new Date().toISOString(), - mainEntity: { - '@type': 'Article', - headline: `${selectedZodiac.value}座今日运势`, - description: fortune.value?.shortcomment || `${selectedZodiac.value}座运势分析`, - author: { - '@type': 'Organization', - name: 'Tomda' - } - } - } -}) - -// SEO优化 - 动态更新头部信息 -const updateHeadInfo = () => { +watch([selectedZodiac, fortune], () => { useHead({ title: pageTitle.value, meta: [ { name: 'description', content: pageDescription.value }, - { name: 'keywords', content: `${selectedZodiac.value}座,星座运势,今日运势,运程预测,星座运程,爱情运势,事业运势,财运预测` } + { name: 'keywords', content: `${selectedZodiac.value}座,星座运势,今日运势,运程预测,UIED工具,免费星座查询` } ], script: [ { type: 'application/ld+json', - children: JSON.stringify(structuredData.value) - } - ], - link: [ - { - rel: 'canonical', - href: `${window.location.origin}${route.path}` + children: JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'SoftwareApplication', + 'name': `${selectedZodiac.value}座运势查询工具`, + 'applicationCategory': 'LifestyleApplication', + 'operatingSystem': 'Any', + 'offers': { + '@type': 'Offer', + 'price': '0', + 'priceCurrency': 'CNY' + }, + 'description': pageDescription.value, + 'mainEntity': { + '@type': 'Article', + 'headline': `${selectedZodiac.value}座今日运势分析`, + 'image': `https://www.uiedtool.com/assets/zodiac/${selectedZodiac.value}.png`, // 示例路径 + 'datePublished': new Date().toISOString(), + 'author': { + '@type': 'Organization', + 'name': 'UIED Tools' + } + } + }) } ] }) -} - -// 监听运势数据变化,更新SEO信息 -watch([selectedZodiac, fortune], () => { - updateHeadInfo() }) - diff --git a/src/components/Tools/icons.ts b/src/components/Tools/icons.ts index 8935bdd..adad108 100644 --- a/src/components/Tools/icons.ts +++ b/src/components/Tools/icons.ts @@ -519,9 +519,17 @@ export const toolIcons = { type: 'svg', content: '' }, + promptReverse: { + type: 'svg', + content: '' + }, calendar: { type: 'svg', content: '' + }, + microphone: { + type: 'svg', + content: '' } } as const diff --git a/src/components/Tools/tools.ts b/src/components/Tools/tools.ts index e2ef818..029fa3f 100644 --- a/src/components/Tools/tools.ts +++ b/src/components/Tools/tools.ts @@ -113,6 +113,17 @@ export function getToolsCate(): ToolCategory[] { desc: '专业的 AI 绘图提示词编辑工具,支持可视化编辑和智能优化', url: '/tools/ai/prompt-editor', cate: 'AI提示词' + }, + { + id: 406, + title: '免费图片提示词反推', + logo: { type: 'svg', name: 'promptReverse' }, + desc: '上传图片智能反推提示词,支持Flux、Stable Diffusion、Midjourney等多种模型', + url: '/tools/ai/prompt-reverse', + cate: 'AI图像工具', + releaseDate: '2025/12/02 00:00:00', + tags: ['免费', '新品'], + isNew: true } ] }, @@ -236,6 +247,17 @@ export function getToolsCate(): ToolCategory[] { releaseDate: '2024/3/20 00:00:00', tags: ['免费', '新品'], isNew: true + }, + { + id: 602, + title: '免费在线文本配音', + logo: { type: 'svg', name: 'microphone' }, + desc: '免费在线文本转语音工具,支持多种角色和情感风格,一键生成自然流畅的语音配音', + url: '/tools/ai/text-to-speech', + cate: 'AI效率工具', + releaseDate: '2024/12/03 00:00:00', + tags: ['免费', '新品'], + isNew: true } ] } diff --git a/src/router/router.ts b/src/router/router.ts index 39a1575..311ab02 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -717,6 +717,26 @@ export const constantRoute = [ description: '使用 DeepSeek AI 生成走心的新年朋友圈文案,让你的新年祝福与众不同。' } }, + { + path: '/tools/ai/prompt-reverse', + component: () => import('@/components/Tools/AI/PromptReverse.vue'), + name: 'promptReverse', + meta: { + title: "免费图片提示词反推", + keywords: '提示词反推,图片转提示词,AI提示词生成,Flux提示词,Midjourney提示词', + description: '上传图片智能反推提示词,支持Flux、Stable Diffusion、Midjourney等多种模型,一键生成精准提示词', + } + }, + { + path: '/tools/ai/text-to-speech', + component: () => import('@/components/Tools/AI/TextToSpeech.vue'), + name: 'textToSpeech', + meta: { + title: "免费在线文本配音", + keywords: '文本转语音,在线配音,AI配音,文字转语音,免费配音工具', + description: '免费在线文本转语音工具,支持多种角色和情感风格,一键生成自然流畅的语音配音', + } + }, // 关于 { path: '/about', diff --git a/ssr.config.ts b/ssr.config.ts index 873a850..8128725 100644 --- a/ssr.config.ts +++ b/ssr.config.ts @@ -21,7 +21,8 @@ export function seoperender(options?: SeoOptions) { '/tools/img-cut', '/tools/img-format', '/tools/img-to-pdf', - '/tools/pdf-to-images' + '/tools/pdf-to-images', + '/tools/ai/prompt-reverse' ]; return vitePluginSeoPrerender({ From a411d1bc71827fc49df7cf2d2753bc35efa6c2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E5=90=8DTomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Fri, 5 Dec 2025 20:04:54 +0800 Subject: [PATCH 03/45] feat: add AI Remove Watermark tool, update AIChat features and icons --- src/components/Home/Changelog.vue | 63 +- src/components/Tools/AI/AIChat.vue | 1087 ++++++++++++++++ src/components/Tools/AI/DeepSeekR1.vue | 1288 +++++-------------- src/components/Tools/AI/RemoveWatermark.vue | 291 +++++ src/components/Tools/icons.ts | 8 + src/components/Tools/tools.ts | 22 + src/router/router.ts | 20 + 7 files changed, 1823 insertions(+), 956 deletions(-) create mode 100644 src/components/Tools/AI/AIChat.vue create mode 100644 src/components/Tools/AI/RemoveWatermark.vue diff --git a/src/components/Home/Changelog.vue b/src/components/Home/Changelog.vue index 1e1affb..8f9af14 100644 --- a/src/components/Home/Changelog.vue +++ b/src/components/Home/Changelog.vue @@ -12,8 +12,8 @@ import { ref, onMounted, onUnmounted, watch, type ComponentPublicInstance } from * * @author Tomda * @createDate 2025-01-09 - * @lastUpdate 2025-12-03 10:00 - * @version Beta 2.3.2 + * @lastUpdate 2025-12-03 16:00 + * @version Beta 2.3.3 * @toolsCount 当前工具总数:90个 */ @@ -243,7 +243,7 @@ onUnmounted(() => {
- 当前工具总数:90个 | 最后更新:2025-12-03 10:00 + 当前工具总数:90个 | 最后更新:2025-12-03 16:00
@@ -280,6 +280,63 @@ onUnmounted(() => {
+ +
+
+ 2.3.3 + 2025-12-03 16:00 +
+
+
+ 更新 + AI对话助手与DeepSeek R1重大更新 +
+
+
    +
  • +
    + + AI对话助手 (AIChat) 界面重构 + + + + +
    +
    +
      +
    • 界面升级:采用 Ant Design X 极简风格,优化输入框圆角与阴影,提升视觉体验。
    • +
    • 交互优化:办公智能体移至主对话区“快速提示词”,新增代码解释、周报生成等8种常用场景。
    • +
    • 功能增强:新增系统提示词与温度设置功能;顶部增加AI知识库等实用导航链接(新窗口打开)。
    • +
    • 细节打磨:模型选择增加SVG图标,消息气泡样式微调,响应式布局优化。
    • +
    +
    +
  • +
  • +
    + + DeepSeek R1 修复与优化 + + + + +
    +
    +
      +
    • 修复 CSS 构建错误,优化思考动画与代码块样式。
    • +
    +
    +
  • +
+
+
+
+
diff --git a/src/components/Tools/AI/AIChat.vue b/src/components/Tools/AI/AIChat.vue new file mode 100644 index 0000000..eeb0d26 --- /dev/null +++ b/src/components/Tools/AI/AIChat.vue @@ -0,0 +1,1087 @@ + + + + + diff --git a/src/components/Tools/AI/DeepSeekR1.vue b/src/components/Tools/AI/DeepSeekR1.vue index ff1b34f..0db4f80 100644 --- a/src/components/Tools/AI/DeepSeekR1.vue +++ b/src/components/Tools/AI/DeepSeekR1.vue @@ -18,10 +18,10 @@
-
+
-
+
@@ -257,6 +260,7 @@ import * as pdfjsLib from 'pdfjs-dist' import { Document, Upload, Delete } from '@element-plus/icons-vue' import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue' import ToolsRecommend from '@/components/Common/ToolsRecommend.vue' +import UsageGuide from '@/components/Common/UsageGuide.vue' import { useRoute } from 'vue-router' const route = useRoute() @@ -274,6 +278,18 @@ const quality = ref(150) const converting = ref(false) const fileInput = ref(null) +const guideSteps = [ + { title: '上传PDF文件', description: '点击上传区域或直接拖拽PDF文件到指定区域,支持批量上传。' }, + { title: '选择质量', description: '选择普通(150dpi)或高清(300dpi)图片质量。' }, + { title: '转换下载', description: '点击“开始转换”按钮,系统将自动转换并打包下载所有图片。' } +] + +const guideNotes = [ + '转换过程完全在本地进行,不会消耗您的流量,也不会上传文件。', + '单个文件限制500MB,页数不超过1000页。', + '转换后的图片格式为PNG。' +] + // 触发文件选择 const triggerFileInput = () => { fileInput.value?.click() @@ -370,31 +386,32 @@ const convertPdfToImages = async (file: File) => { // 拖放处理 onMounted(async () => { - const dropZone = document.querySelector('.border-dashed') - if (!dropZone) return - - dropZone.addEventListener('dragover', ((e: Event) => { - e.preventDefault() - if (e instanceof DragEvent) { - dropZone.classList.add('border-blue-500') - } - }) as EventListener) - - dropZone.addEventListener('dragleave', () => { - dropZone.classList.remove('border-blue-500') - }) - - dropZone.addEventListener('drop', ((e: Event) => { - e.preventDefault() - if (e instanceof DragEvent && e.dataTransfer) { - dropZone.classList.remove('border-blue-500') - const droppedFiles = e.dataTransfer.files - const pdfFiles = Array.from(droppedFiles).filter((file: File) => file.type.includes('pdf')) - files.value.push(...pdfFiles) - } - }) as EventListener) + // const dropZone = document.querySelector('.border-dashed') + // if (!dropZone) return + + // dropZone.addEventListener('dragover', ((e: Event) => { + // e.preventDefault() + // if (e instanceof DragEvent) { + // dropZone.classList.add('border-blue-500') + // } + // }) as EventListener) + + // dropZone.addEventListener('dragleave', () => { + // dropZone.classList.remove('border-blue-500') + // }) + + // dropZone.addEventListener('drop', ((e: Event) => { + // e.preventDefault() + // if (e instanceof DragEvent && e.dataTransfer) { + // dropZone.classList.remove('border-blue-500') + // const droppedFiles = e.dataTransfer.files + // const pdfFiles = Array.from(droppedFiles).filter((file: File) => file.type.includes('pdf')) + // files.value.push(...pdfFiles) + // } + // }) as EventListener) // 动态加载 PDF Worker + // @ts-ignore const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.js') pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker.default }) @@ -420,6 +437,16 @@ const clearFiles = () => { // 添加拖拽状态 const isDragging = ref(false) +const handleDragover = (e: DragEvent) => { + e.preventDefault() + isDragging.value = true +} + +const handleDragleave = (e: DragEvent) => { + e.preventDefault() + isDragging.value = false +} + // 在 script setup 部分添加 handleDrop 方法 const handleDrop = (e: DragEvent) => { e.preventDefault() diff --git a/src/components/Tools/PdfWatermark/index.vue b/src/components/Tools/PdfWatermark/index.vue new file mode 100644 index 0000000..6b232b2 --- /dev/null +++ b/src/components/Tools/PdfWatermark/index.vue @@ -0,0 +1,455 @@ + + + + + + + diff --git a/src/components/Tools/Pomodoro/index.vue b/src/components/Tools/Pomodoro/index.vue new file mode 100644 index 0000000..9c6cdf0 --- /dev/null +++ b/src/components/Tools/Pomodoro/index.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/src/components/Tools/Relationship/Relationship.vue b/src/components/Tools/Relationship/Relationship.vue new file mode 100644 index 0000000..1d8b9b9 --- /dev/null +++ b/src/components/Tools/Relationship/Relationship.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/src/components/Tools/ScreenRecorder/index.vue b/src/components/Tools/ScreenRecorder/index.vue new file mode 100644 index 0000000..61096ee --- /dev/null +++ b/src/components/Tools/ScreenRecorder/index.vue @@ -0,0 +1,321 @@ + + + + + \ No newline at end of file diff --git a/src/components/Tools/TextToPdf/index.vue b/src/components/Tools/TextToPdf/index.vue new file mode 100644 index 0000000..247f14a --- /dev/null +++ b/src/components/Tools/TextToPdf/index.vue @@ -0,0 +1,277 @@ + + + + + diff --git a/src/components/Tools/TodoList/index.vue b/src/components/Tools/TodoList/index.vue new file mode 100644 index 0000000..58ba60f --- /dev/null +++ b/src/components/Tools/TodoList/index.vue @@ -0,0 +1,226 @@ + + + + + + + diff --git a/src/components/Tools/WordCount/index.vue b/src/components/Tools/WordCount/index.vue new file mode 100644 index 0000000..7f47708 --- /dev/null +++ b/src/components/Tools/WordCount/index.vue @@ -0,0 +1,260 @@ + + + + + \ No newline at end of file diff --git a/src/components/Tools/icons.ts b/src/components/Tools/icons.ts index e370e5e..9808c88 100644 --- a/src/components/Tools/icons.ts +++ b/src/components/Tools/icons.ts @@ -1,8 +1,68 @@ export const toolIcons = { + snake: { + type: 'svg', + content: '' + }, + minesweeper: { + type: 'svg', + content: '' + }, + game: { + type: 'svg', + content: '' + }, + typingRain: { + type: 'svg', + content: '' + }, + relationship: { + type: 'svg', + content: '' + }, + base64: { + type: 'svg', + content: '' + }, aiChat: { type: 'svg', content: '' }, + pdfEncrypt: { + type: 'svg', + content: '' + }, + pdfPageNumber: { + type: 'svg', + content: '' + }, + pdfSign: { + type: 'svg', + content: '' + }, + pdfExtractText: { + type: 'svg', + content: '' + }, + csvToExcel: { + type: 'svg', + content: '' + }, + excelToCsv: { + type: 'svg', + content: '' + }, + pdfWatermark: { + type: 'svg', + content: '' + }, + excelToJson: { + type: 'svg', + content: '' + }, + jsonToExcel: { + type: 'svg', + content: '' + }, deepseek: { type: 'svg', content: '' @@ -51,6 +111,14 @@ export const toolIcons = { type: 'svg', content: '' }, + markdownToPdf: { + type: 'svg', + content: '' + }, + wordCount: { + type: 'svg', + content: '' + }, imageToGif: { type: 'svg', content: '' @@ -159,10 +227,6 @@ export const toolIcons = { type: 'svg', content: '' }, - wordCount: { - type: 'svg', - content: '' - }, textRemoveDuplicate: { type: 'svg', content: '' @@ -604,6 +668,46 @@ export const toolIcons = { type: 'svg', content: '' }, + textToPdf: { + type: 'svg', + content: '' + }, + dateCalculator: { + type: 'svg', + content: '' + }, + screenRecorder: { + type: 'svg', + content: '' + }, + todoList: { + type: 'svg', + content: '' + }, + pomodoro: { + type: 'svg', + content: '' + }, + weather: { + type: 'svg', + content: '' + }, + bmi: { + type: 'svg', + content: '' + }, + stopwatch: { + type: 'svg', + content: '' + }, + ageCalculator: { + type: 'svg', + content: '' + }, + lifeProgress: { + type: 'svg', + content: '' + }, } as const export type ToolIconName = keyof typeof toolIcons diff --git a/src/components/Tools/tools.ts b/src/components/Tools/tools.ts index 3b6b2db..d4c0a72 100644 --- a/src/components/Tools/tools.ts +++ b/src/components/Tools/tools.ts @@ -487,6 +487,263 @@ export function getToolsCate(): ToolCategory[] { desc: '在线压缩PDF文件大小,支持批量处理,本地压缩更安全,适合邮件发送和文件上传', url: '/tools/pdf-compress', cate: 'PDF工具' + }, + { + id: 618, + title: 'PDF添加水印', + logo: { type: 'svg', name: 'pdfWatermark' }, + desc: '免费在线PDF添加水印工具,支持自定义文字、大小、颜色、透明度和旋转角度,本地处理更安全。', + url: '/tools/pdf-watermark', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 619, + title: 'PDF加密', + logo: { type: 'svg', name: 'pdfEncrypt' }, + desc: '免费在线PDF加密工具,支持设置打开密码和权限密码,本地处理更安全。', + url: '/tools/pdf-encrypt', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 620, + title: 'PDF添加页码', + logo: { type: 'svg', name: 'pdfPageNumber' }, + desc: '免费在线PDF添加页码工具,支持自定义位置、格式和字体样式,本地处理更安全。', + url: '/tools/pdf-page-number', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 625, + title: 'PDF签名', + logo: { type: 'svg', name: 'pdfSign' }, + desc: '免费在线PDF签名工具,支持手写签名并添加到PDF文件中,本地处理更安全。', + url: '/tools/pdf-sign', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 626, + title: 'PDF文本提取', + logo: { type: 'svg', name: 'pdfExtractText' }, + desc: '免费在线提取PDF文件中的文本内容,支持复制和导出TXT,本地处理更安全。', + url: '/tools/pdf-extract-text', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 627, + title: '文本转PDF', + logo: { type: 'svg', name: 'textToPdf' }, + desc: '在线将文本内容转换为PDF文档,支持自定义排版', + url: '/tools/text-to-pdf', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 628, + title: 'Markdown转PDF', + logo: { type: 'svg', name: 'markdownToPdf' }, + desc: '在线将Markdown文档转换为PDF,支持代码高亮和实时预览', + url: '/tools/markdown-to-pdf', + cate: 'PDF工具', + isNew: true, + tags: ['免费', '新品'] + } + ] + }, + { + id: 62, + title: '表格工具', + list: [ + { + id: 621, + title: 'Excel转JSON', + logo: { type: 'svg', name: 'excelToJson' }, + desc: '在线将Excel文件转换为JSON格式,支持.xlsx, .xls格式,本地处理更安全。', + url: '/tools/excel-to-json', + cate: '表格工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 622, + title: 'JSON转Excel', + logo: { type: 'svg', name: 'jsonToExcel' }, + desc: '在线将JSON数据转换为Excel文件,支持数组格式JSON,本地处理更安全。', + url: '/tools/json-to-excel', + cate: '表格工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 623, + title: 'CSV转Excel', + logo: { type: 'svg', name: 'csvToExcel' }, + desc: '在线将CSV文件转换为Excel (.xlsx)格式,自动处理编码问题,本地处理更安全。', + url: '/tools/csv-to-excel', + cate: '表格工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 624, + title: 'Excel转CSV', + logo: { type: 'svg', name: 'excelToCsv' }, + desc: '在线将Excel文件转换为CSV格式,支持.xlsx, .xls格式,本地处理更安全。', + url: '/tools/excel-to-csv', + cate: '表格工具', + isNew: true, + tags: ['免费', '新品'] + } + ] + }, + { + id: 63, + title: '文档工具', + list: [ + { + id: 631, + title: '字数统计', + logo: { type: 'svg', name: 'wordCount' }, + desc: '在线字数统计工具,支持字符数、单词数、行数、段落数统计,实时计算阅读时间', + url: '/tools/word-count', + cate: '文档工具', + isNew: true, + tags: ['免费', '新品'] + } + ] + }, + { + id: 64, + title: '辅助工具', + list: [ + { + id: 641, + title: '日期计算器', + logo: { type: 'svg', name: 'dateCalculator' }, + desc: '在线日期计算器,支持日期间隔计算和日期推算', + url: '/tools/date-calculator', + cate: '辅助工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 642, + title: '在线屏幕录制', + logo: { type: 'svg', name: 'screenRecorder' }, + desc: '免费在线屏幕录制工具,支持录制系统声音,本地录制更安全', + url: '/tools/screen-recorder', + cate: '辅助工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 643, + title: '亲戚称呼计算器', + logo: { type: 'svg', name: 'relationship' }, + desc: '中国亲戚关系称呼查询,支持互查,逢年过节必备神器', + url: '/tools/relationship', + cate: '辅助工具', + isNew: true, + tags: ['免费', '新品'] + } + ] + }, + { + id: 65, + title: '效率工具', + list: [ + { + id: 651, + title: '待办清单', + logo: { type: 'svg', name: 'todoList' }, + desc: '极简风格的待办事项清单,支持任务管理、优先级设置,帮助您高效管理日常任务', + url: '/tools/todo-list', + cate: '效率工具', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 652, + title: '番茄钟', + logo: { type: 'svg', name: 'pomodoro' }, + desc: '基于番茄工作法的专注时钟,支持自定义工作/休息时长,助您保持专注高效', + url: '/tools/pomodoro', + cate: '效率工具', + isNew: true, + tags: ['免费', '新品'] + } + ] + } + ] + }, + { + id: 8, + title: '生活常用', + icon: '', + list: [ + { + id: 81, + title: '实用查询', + list: [ + { + id: 811, + title: '天气查询', + logo: { type: 'svg', name: 'weather' }, + desc: '免费天气预报查询,支持全球城市,提供实时温度、湿度、风速等详细气象信息', + url: '/tools/daily/weather', + cate: '实用查询', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 812, + title: 'BMI计算器', + logo: { type: 'svg', name: 'bmi' }, + desc: '在线计算身体质量指数(BMI),评估身体健康状况', + url: '/tools/daily/bmi', + cate: '实用查询', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 813, + title: '在线秒表', + logo: { type: 'svg', name: 'stopwatch' }, + desc: '简单好用的在线秒表工具,支持计次功能', + url: '/tools/daily/stopwatch', + cate: '实用查询', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 814, + title: '年龄计算器', + logo: { type: 'svg', name: 'ageCalculator' }, + desc: '在线计算精确年龄,包含周岁、虚岁、生肖及星座', + url: '/tools/daily/age-calculator', + cate: '实用查询', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 815, + title: '人生进度条', + logo: { type: 'svg', name: 'lifeProgress' }, + desc: '可视化展示人生进度,计算已度过的时间和剩余时间', + url: '/tools/daily/life-progress', + cate: '实用查询', + isNew: true, + tags: ['免费', '新品'] } ] } @@ -1088,6 +1345,16 @@ export function getToolsCate(): ToolCategory[] { cateId: 2, cate: '开发运维' }, + { + id: 2114, + title: 'Base64转换工具', + logo: { type: 'svg', name: 'base64' }, + desc: '支持文本/图片与Base64编码之间的相互转换', + url: '/tools/base64', + cateId: 2, + cate: '开发运维', + isNew: true + }, { id: 216, title: 'Json在线转换', @@ -1259,6 +1526,72 @@ export function getToolsCate(): ToolCategory[] { isNew: true } ] + }, + { + id: 74, + title: '摸鱼游戏', + list: [ + { + id: 741, + title: '打字雨 (中文)', + logo: { type: 'svg', name: 'typingRain' }, + desc: '经典的打字雨游戏中文版,锻炼打字速度与反应能力', + url: '/tools/games/typing-rain-cn', + cate: '摸鱼游戏', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 742, + title: '打字雨 (English)', + logo: { type: 'svg', name: 'typingRain' }, + desc: 'Classic Typing Rain game, test your English typing speed', + url: '/tools/games/typing-rain-en', + cate: '摸鱼游戏', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 743, + title: '贪吃蛇', + logo: { type: 'svg', name: 'snake' }, + desc: '经典的贪吃蛇游戏,控制蛇吃食物变长,挑战最高分', + url: '/tools/games/snake', + cate: '摸鱼游戏', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 744, + title: '扫雷', + logo: { type: 'svg', name: 'minesweeper' }, + desc: '经典的扫雷游戏,运用逻辑推理避开地雷,锻炼大脑', + url: '/tools/games/minesweeper', + cate: '摸鱼游戏', + isNew: true, + tags: ['免费', '新品'] + }, + { + id: 745, + title: '电子木鱼', + logo: { type: 'svg', name: 'game' }, + desc: '在线敲木鱼,积攒功德,放松心情,净化心灵', + url: '/tools/games/woodfish', + cate: '摸鱼游戏', + isNew: true, + tags: ['免费', '解压'] + }, + { + id: 746, + title: '2048', + logo: { type: 'svg', name: 'game' }, + desc: '经典的数字合成游戏,移动方块合并数字,挑战2048', + url: '/tools/games/2048', + cate: '摸鱼游戏', + isNew: true, + tags: ['免费', '益智'] + } + ] } ] }, diff --git a/src/router/router.ts b/src/router/router.ts index 1587021..3fb7888 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -184,8 +184,8 @@ export const constantRoute = [ name: 'imageToPdf', meta: { title: "图片转PDF", - keywords: '图片转PDF,JPG转PDF,PNG转PDF', - description: '在线图片转PDF工具,支持多张图片合并成PDF', + keywords: '图片转PDF,JPG转PDF,PNG转PDF,图片合并PDF,创建PDF', + description: '在线图片转PDF工具,支持JPG、PNG等多种格式图片合并成PDF,自定义页面大小和边距,本地处理更安全。' } }, { @@ -204,17 +204,18 @@ export const constantRoute = [ name: 'pdfMerge', meta: { title: "免费在线PDF合并工具", - keywords: 'PDF合并,PDF合并工具,在线PDF合并,免费PDF合并', - description: '免费在线PDF合并工具,支持多个PDF文件合并,无需上传至云端,本地处理更安全。' + keywords: 'PDF合并,PDF合并工具,在线PDF合并,免费PDF合并,PDF文件合并,合并PDF', + description: '免费在线PDF合并工具,支持多个PDF文件合并,无需上传至云端,本地处理更安全。支持调整合并顺序。' } }, { path: '/tools/pdf-split', component: () => import('@/components/Tools/PdfSplit/index.vue'), + name: 'pdfSplit', meta: { title: '免费在线PDF分割工具', - keywords: 'PDF分割,PDF拆分,PDF分页,在线PDF分割,免费PDF分割', - description: '免费在线PDF分割工具,支持将PDF拆分为单页,批量处理多个文件,本地处理更安全。' + keywords: 'PDF分割,PDF拆分,PDF分页,在线PDF分割,免费PDF分割,PDF提取页面', + description: '免费在线PDF分割工具,支持将PDF拆分为单页,提取指定页面,批量处理多个文件,本地处理更安全。' } }, { @@ -223,8 +224,8 @@ export const constantRoute = [ name: 'pdfRotate', meta: { title: "PDF页面旋转", - keywords: 'PDF旋转,PDF页面旋转,PDF文档旋转,在线PDF旋转', - description: '在线PDF页面旋转工具,支持批量旋转、单独旋转页面,同时可调整页面顺序', + keywords: 'PDF旋转,PDF页面旋转,PDF文档旋转,在线PDF旋转,旋转PDF', + description: '在线PDF页面旋转工具,支持批量旋转、单独旋转页面,同时可调整页面顺序,本地处理更安全。' } }, { @@ -233,8 +234,8 @@ export const constantRoute = [ name: 'pdfDelete', meta: { title: "PDF页面删除", - keywords: 'PDF删除页面,PDF页面删除,PDF文档编辑,在线PDF删除', - description: '在线PDF页面删除工具,支持删除指定页面,同时可调整页面顺序和旋转页面', + keywords: 'PDF删除页面,PDF页面删除,PDF文档编辑,在线PDF删除,删除PDF页', + description: '在线PDF页面删除工具,支持删除指定页面,同时可调整页面顺序和旋转页面,本地处理更安全。' } }, { @@ -243,8 +244,169 @@ export const constantRoute = [ name: 'pdfCompress', meta: { title: "免费PDF压缩工具", - keywords: 'PDF压缩,PDF文件压缩,在线PDF压缩,免费PDF压缩', - description: '在线压缩PDF文件大小,支持批量处理,本地压缩更安全,适合邮件发送和文件上传', + keywords: 'PDF压缩,PDF文件压缩,在线PDF压缩,免费PDF压缩,缩小PDF', + description: '在线压缩PDF文件大小,支持批量处理,本地压缩更安全,适合邮件发送和文件上传,保持良好画质。' + } + }, + { + path: '/tools/pdf-watermark', + component: () => import('@/components/Tools/PdfWatermark/index.vue'), + name: 'pdfWatermark', + meta: { + title: "PDF添加水印", + keywords: 'PDF水印,PDF加水印,PDF添加水印,在线PDF水印,文本水印', + description: '免费在线PDF添加水印工具,支持自定义文字、大小、颜色、透明度和旋转角度,本地处理更安全。' + } + }, + { + path: '/tools/pdf-encrypt', + component: () => import('@/components/Tools/PdfEncrypt/index.vue'), + name: 'pdfEncrypt', + meta: { + title: "PDF加密", + keywords: 'PDF加密,PDF密码保护,PDF设置密码,在线PDF加密,保护PDF', + description: '免费在线PDF加密工具,支持设置打开密码和权限密码,防止文件被未授权访问,本地处理更安全。' + } + }, + { + path: '/tools/pdf-page-number', + component: () => import('@/components/Tools/PdfPageNumber/index.vue'), + name: 'pdfPageNumber', + meta: { + title: "PDF添加页码", + keywords: 'PDF页码,PDF添加页码,PDF页码设置,在线PDF页码,PDF插入页码', + description: '免费在线PDF添加页码工具,支持自定义位置、格式和样式,本地处理更安全。' + } + }, + { + path: '/tools/pdf-sign', + component: () => import('@/components/Tools/PdfSign/index.vue'), + name: 'pdfSign', + meta: { + title: "PDF签名", + keywords: 'PDF签名,PDF电子签名,在线PDF签名,PDF手写签名,签署PDF', + description: '免费在线PDF签名工具,支持手写签名并添加到PDF文件中,无需打印扫描,本地处理更安全。' + } + }, + { + path: '/tools/pdf-extract-text', + component: () => import('@/components/Tools/PdfExtractText/index.vue'), + name: 'pdfExtractText', + meta: { + title: "PDF文本提取", + keywords: 'PDF文本提取,PDF转TXT,PDF复制文本,PDF文字识别,提取PDF内容', + description: '免费在线提取PDF文件中的文本内容,支持复制和导出TXT,本地处理更安全。' + } + }, + { + path: '/tools/text-to-pdf', + component: () => import('@/components/Tools/TextToPdf/index.vue'), + name: 'textToPdf', + meta: { + title: "文本转PDF", + keywords: '文本转PDF,TXT转PDF,在线文本转PDF,生成PDF', + description: '在线将文本内容转换为PDF文档,支持自定义字体大小和排版,本地处理更安全。' + } + }, + { + path: '/tools/markdown-to-pdf', + component: () => import('@/components/Tools/MarkdownToPdf/index.vue'), + name: 'markdownToPdf', + meta: { + title: "Markdown转PDF", + keywords: 'Markdown转PDF,MD转PDF,在线Markdown转PDF,生成PDF', + description: '在线将Markdown文档转换为PDF,支持代码高亮、实时预览和自定义排版,本地处理更安全。' + } + }, + { + path: '/tools/word-count', + component: () => import('@/components/Tools/WordCount/index.vue'), + name: 'wordCount', + meta: { + title: "在线字数统计", + keywords: '字数统计,在线字数统计,字符统计,单词统计,行数统计,阅读时间计算', + description: '免费在线字数统计工具,实时统计字符数、单词数、行数、段落数,支持中英文混合统计,本地处理更安全。' + } + }, + { + path: '/tools/date-calculator', + component: () => import('@/components/Tools/DateCalculator/index.vue'), + name: 'dateCalculator', + meta: { + title: "日期计算器", + keywords: '日期计算器,日期推算,天数计算,日期间隔计算,在线日期计算器', + description: '在线日期计算器,支持计算两个日期之间的天数间隔,以及根据日期往后推算未来日期,方便快捷。' + } + }, + { + path: '/tools/screen-recorder', + component: () => import('@/components/Tools/ScreenRecorder/index.vue'), + name: 'screenRecorder', + meta: { + title: "在线屏幕录制", + keywords: '屏幕录制,在线录屏,网页录屏,无需安装,免费录屏,录制系统声音', + description: '免费在线屏幕录制工具,无需安装软件,支持录制屏幕、窗口或标签页,支持录制系统声音,本地录制更安全。' + } + }, + { + path: '/tools/relationship', + component: () => import('@/components/Tools/Relationship/Relationship.vue'), + name: 'relationship', + meta: { + title: "亲戚称呼计算器", + keywords: '亲戚计算器,称呼计算器,亲戚关系,三姑六婆', + description: '中国亲戚关系称呼查询,支持互查,逢年过节必备神器', + } + }, + { + path: '/tools/base64', + component: () => import('@/components/Tools/Base64/Base64.vue'), + name: 'base64', + meta: { + title: "Base64转换工具", + keywords: 'Base64编码,Base64解码,图片转Base64,Base64转图片', + description: '支持文本/图片与Base64编码之间的相互转换,本地处理更安全', + } + }, + // 表格工具 + { + path: '/tools/excel-to-json', + component: () => import('@/components/Tools/ExcelToJson/index.vue'), + name: 'excelToJson', + meta: { + title: "Excel转JSON", + keywords: 'Excel转JSON,Excel转JSON工具,在线Excel转JSON', + description: '在线将Excel文件转换为JSON格式,支持.xlsx, .xls格式,本地处理更安全。', + } + }, + { + path: '/tools/json-to-excel', + component: () => import('@/components/Tools/JsonToExcel/index.vue'), + name: 'jsonToExcel', + meta: { + title: "JSON转Excel", + keywords: 'JSON转Excel,JSON转Excel工具,在线JSON转Excel', + description: '在线将JSON数据转换为Excel文件,支持数组格式JSON,本地处理更安全。', + } + }, + { + path: '/tools/csv-to-excel', + component: () => import('@/components/Tools/CsvToExcel/index.vue'), + name: 'csvToExcel', + meta: { + title: "CSV转Excel", + keywords: 'CSV转Excel,CSV转XLSX,在线CSV转换', + description: '在线将CSV文件转换为Excel (.xlsx)格式,自动处理编码问题,本地处理更安全。', + } + }, + { + path: '/tools/excel-to-csv', + component: () => import('@/components/Tools/ExcelToCsv/index.vue'), + name: 'excelToCsv', + meta: { + title: "Excel转CSV", + keywords: 'Excel转CSV,XLSX转CSV,在线Excel转换', + description: '在线将Excel文件转换为CSV格式,支持自定义分隔符,本地处理更安全。', } }, //工具 @@ -308,16 +470,7 @@ export const constantRoute = [ description: '在线字数计数器,主要是方便计算字数,以控制文字数量的小工具(小说作者、论文、文档、文字编辑必备工具)。', } }, - { - path: '/tools/ip', - component: () => import('@/components/Tools/Ip/Ip.vue'), - name: 'ip', - meta: { - title: "IP查询", - keywords: 'ip,ip查询,ip地址查询,ip138,查ip,我的ip,公网ip,ip归属地查询', - description: '公网ip地址归属地查询', - } - }, + { path: '/tools/scaletran', component: () => import('@/components/Tools/ScaleTran/ScaleTran.vue'), @@ -1361,6 +1514,66 @@ export const constantRoute = [ description: '在线查看摸鱼日历,了解距离各种假期的剩余时间,支持历史日期查询', } }, + { + path: '/tools/games/typing-rain-cn', + component: () => import('@/components/Tools/Games/TypingRain/TypingRain.vue'), + name: 'typingRainCn', + meta: { + title: "打字雨(中文版)", + keywords: '打字游戏,打字练习,中文打字,趣味打字,摸鱼小游戏', + description: '经典的打字雨游戏中文版,在单词落下前输入正确的拼音或汉字,锻炼打字速度与反应能力', + } + }, + { + path: '/tools/games/typing-rain-en', + component: () => import('@/components/Tools/Games/TypingRain/TypingRain.vue'), + name: 'typingRainEn', + meta: { + title: "打字雨(英文版)", + keywords: 'Typing Game,Typing Rain,英文打字,打字练习,摸鱼小游戏', + description: 'Classic Typing Rain game, type the falling words before they hit the ground. Test your typing speed and accuracy.', + } + }, + { + path: '/tools/games/snake', + component: () => import('@/components/Tools/Games/Snake/Snake.vue'), + name: 'snake', + meta: { + title: "贪吃蛇", + keywords: '贪吃蛇,Snake,经典游戏,摸鱼小游戏,网页游戏', + description: '经典的贪吃蛇游戏,控制蛇吃食物变长,挑战最高分,重温童年回忆。', + } + }, + { + path: '/tools/games/minesweeper', + component: () => import('@/components/Tools/Games/Minesweeper/Minesweeper.vue'), + name: 'minesweeper', + meta: { + title: "扫雷", + keywords: '扫雷,Minesweeper,经典游戏,益智游戏,摸鱼小游戏', + description: '经典的扫雷游戏,运用逻辑推理避开地雷,挑战不同难度,锻炼大脑。', + } + }, + { + path: '/tools/games/woodfish', + component: () => import('@/components/Tools/Games/Woodfish/Woodfish.vue'), + name: 'woodfish', + meta: { + title: "电子木鱼", + keywords: '电子木鱼,积攒功德,解压工具,摸鱼神器,在线木鱼', + description: '在线电子木鱼,点击屏幕敲击木鱼,积攒功德,放松心情,净化心灵。', + } + }, + { + path: '/tools/games/2048', + component: () => import('@/components/Tools/Games/Game2048/Game2048.vue'), + name: 'game2048', + meta: { + title: "2048", + keywords: '2048,益智游戏,数字游戏,合成游戏,经典游戏', + description: '经典的2048数字合成游戏,移动方块合并数字,挑战合成2048!', + } + }, // AI简历生成器 { path: '/tools/ai/resume', @@ -1453,6 +1666,79 @@ export const constantRoute = [ description: '专业的房贷计算器,支持等额本息和等额本金两种还款方式,快速计算月供、利息和还款总额。', } }, + // 生活常用工具 + { + path: '/tools/daily/weather', + component: () => import('@/components/Tools/Daily/Weather/index.vue'), + name: 'weather', + meta: { + title: "天气查询", + keywords: '天气查询,天气预报,实时天气,全球天气', + description: '免费天气预报查询,支持全球城市,提供实时温度、湿度、风速等详细气象信息', + } + }, + { + path: '/tools/daily/bmi', + component: () => import('@/components/Tools/Daily/Bmi/index.vue'), + name: 'bmi', + meta: { + title: "BMI计算器", + keywords: 'BMI计算,身体质量指数,健康计算器', + description: '在线计算身体质量指数(BMI),快速评估您的身体健康状况', + } + }, + { + path: '/tools/daily/stopwatch', + component: () => import('@/components/Tools/Daily/Stopwatch/index.vue'), + name: 'stopwatch', + meta: { + title: "在线秒表", + keywords: '在线秒表,计时器,秒表工具,计次秒表', + description: '简单好用的在线秒表工具,支持毫秒级计时和计次功能', + } + }, + { + path: '/tools/daily/age-calculator', + component: () => import('@/components/Tools/Daily/AgeCalculator/index.vue'), + name: 'ageCalculator', + meta: { + title: "年龄计算器", + keywords: '年龄计算器,周岁计算,虚岁计算,生日倒计时,生肖星座查询', + description: '在线计算精确年龄,包含周岁、虚岁、生肖、星座及下一个生日倒计时', + } + }, + { + path: '/tools/daily/life-progress', + component: () => import('@/components/Tools/Daily/LifeProgress/index.vue'), + name: 'lifeProgress', + meta: { + title: "人生进度条", + keywords: '人生进度条,生命倒计时,时间管理,人生规划', + description: '可视化展示人生进度,计算已度过的时间和剩余时间,助您珍惜当下', + } + }, + + // 效率工具 + { + path: '/tools/todo-list', + component: () => import('@/components/Tools/TodoList/index.vue'), + name: 'todoList', + meta: { + title: "待办清单", + keywords: '待办清单,TodoList,任务管理,日程管理', + description: '极简风格的待办事项清单,支持任务管理、优先级设置,帮助您高效管理日常任务', + } + }, + { + path: '/tools/pomodoro', + component: () => import('@/components/Tools/Pomodoro/index.vue'), + name: 'pomodoro', + meta: { + title: "番茄钟", + keywords: '番茄钟,番茄工作法,专注时钟,时间管理', + description: '基于番茄工作法的专注时钟,支持自定义工作/休息时长,助您保持专注高效', + } + }, ] const router = createRouter({ diff --git a/src/types/relationship.d.ts b/src/types/relationship.d.ts new file mode 100644 index 0000000..8ca6bf6 --- /dev/null +++ b/src/types/relationship.d.ts @@ -0,0 +1 @@ +declare module 'relationship.js'; \ No newline at end of file From 770676a72eef3cc60e5b8b13399c726f3b8538e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Fri, 12 Dec 2025 20:34:29 +0800 Subject: [PATCH 06/45] docs: update changelog tool count and last update date --- src/components/Home/Changelog.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Home/Changelog.vue b/src/components/Home/Changelog.vue index 175ab6c..2d017dc 100644 --- a/src/components/Home/Changelog.vue +++ b/src/components/Home/Changelog.vue @@ -243,7 +243,7 @@ onUnmounted(() => {
- 当前工具总数:168个 | 最后更新:2025-12-11 10:00 + 当前工具总数:176个 | 最后更新:2025-12-12 10:00
From 00755893004cb73b0bd683fc86adf36a1ec4c891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Fri, 12 Dec 2025 20:44:19 +0800 Subject: [PATCH 07/45] feat: add memory card game and fix typing rain fullscreen input issue --- src/components/Home/Changelog.vue | 45 ++- .../Tools/Games/Game2048/Game2048.vue | 6 + .../Tools/Games/MemoryCard/MemoryCard.vue | 304 ++++++++++++++++++ .../Tools/Games/Minesweeper/Minesweeper.vue | 6 + src/components/Tools/Games/Snake/Snake.vue | 6 + .../Tools/Games/TypingRain/TypingRain.vue | 13 +- .../Tools/Games/Woodfish/Woodfish.vue | 6 + src/router/router.ts | 10 + 8 files changed, 389 insertions(+), 7 deletions(-) create mode 100644 src/components/Tools/Games/MemoryCard/MemoryCard.vue diff --git a/src/components/Home/Changelog.vue b/src/components/Home/Changelog.vue index 2d017dc..feeef19 100644 --- a/src/components/Home/Changelog.vue +++ b/src/components/Home/Changelog.vue @@ -12,9 +12,9 @@ import { ref, onMounted, onUnmounted, watch, type ComponentPublicInstance } from * * @author Tomda * @createDate 2025-01-09 - * @lastUpdate 2025-12-12 10:00 - * @version Beta 2.4.1 - * @toolsCount 当前工具总数:176个 + * @lastUpdate 2025-12-12 11:30 + * @version Beta 2.4.2 + * @toolsCount 当前工具总数:177个 */ const tocItems = ref<{ id: string; version: string; date: string; title: string }[]>([]); @@ -243,7 +243,7 @@ onUnmounted(() => {
- 当前工具总数:176个 | 最后更新:2025-12-12 10:00 + 当前工具总数:177个 | 最后更新:2025-12-12 11:30
@@ -280,6 +280,43 @@ onUnmounted(() => {
+ +
+
+ 2.4.2 + 2025-12-12 11:30 +
+
+
+ 更新 + 游戏体验修复与新增 +
+
+
    +
  • +
    新增小游戏
    +
    +
      +
    • 记忆翻牌:考验记忆力的翻牌配对游戏,支持 + 4x4 和 6x6 两种难度。 +
    • +
    +
    +
  • +
  • +
    问题修复
    +
    +
      +
    • 打字雨:修复了全屏模式下输入框无法显示的问题,现在全屏体验更加完美。
    • +
    +
    +
  • +
+
+
+
+
diff --git a/src/components/Tools/Games/Game2048/Game2048.vue b/src/components/Tools/Games/Game2048/Game2048.vue index 3169c25..26015ec 100644 --- a/src/components/Tools/Games/Game2048/Game2048.vue +++ b/src/components/Tools/Games/Game2048/Game2048.vue @@ -100,6 +100,12 @@ + + diff --git a/src/components/Tools/Games/Minesweeper/Minesweeper.vue b/src/components/Tools/Games/Minesweeper/Minesweeper.vue index 1c6edf9..13ae987 100644 --- a/src/components/Tools/Games/Minesweeper/Minesweeper.vue +++ b/src/components/Tools/Games/Minesweeper/Minesweeper.vue @@ -85,6 +85,12 @@ + + diff --git a/src/components/Tools/Psychology/ColorTest.vue b/src/components/Tools/Psychology/ColorTest.vue new file mode 100644 index 0000000..666e7a0 --- /dev/null +++ b/src/components/Tools/Psychology/ColorTest.vue @@ -0,0 +1,145 @@ + + + + diff --git a/src/router/router.ts b/src/router/router.ts index ec2adb1..7627c72 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -1584,6 +1584,26 @@ export const constantRoute = [ description: '经典的记忆翻牌游戏,翻开卡片寻找相同的图案,考验你的瞬间记忆力!', } }, + { + path: '/tools/daily/decision-maker', + component: () => import('@/components/Tools/Daily/DecisionMaker/DecisionMaker.vue'), + name: 'decisionMaker', + meta: { + title: "帮我决定", + keywords: '帮我决定,选择困难症,随机选择,做决定,转盘', + description: '选择困难症福音!输入选项,让运气帮你做决定,快速解决吃什么、去哪玩等难题。', + } + }, + { + path: '/tools/psychology/color-test', + component: () => import('@/components/Tools/Psychology/ColorTest.vue'), + name: 'colorTest', + meta: { + title: "色彩性格测试", + keywords: '色彩性格测试,性格色彩,FPA,性格分析,心理测试', + description: '通过哈特曼色彩性格测试,探索你是红、蓝、白、黄哪种性格,了解你的核心动力和优势。', + } + }, // AI简历生成器 { path: '/tools/ai/resume', From 903042450cad9322bc1464b12fb20838a33f0f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Fri, 12 Dec 2025 20:56:30 +0800 Subject: [PATCH 09/45] fix: move memory card game to game category and add missing icons --- src/components/Tools/icons.ts | 12 ++++++++++++ src/components/Tools/tools.ts | 31 ++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/components/Tools/icons.ts b/src/components/Tools/icons.ts index 9808c88..07e30d2 100644 --- a/src/components/Tools/icons.ts +++ b/src/components/Tools/icons.ts @@ -1,4 +1,16 @@ export const toolIcons = { + memoryCard: { + type: 'svg', + content: '' + }, + decisionMaker: { + type: 'svg', + content: '' + }, + colorTest: { + type: 'svg', + content: '' + }, snake: { type: 'svg', content: '' diff --git a/src/components/Tools/tools.ts b/src/components/Tools/tools.ts index d4c0a72..1d2f4e4 100644 --- a/src/components/Tools/tools.ts +++ b/src/components/Tools/tools.ts @@ -86,7 +86,16 @@ export function getToolsCate(): ToolCategory[] { tags: ['免费', '新品'], isNew: true } - + { + id: 816, + title: '记忆翻牌', + logo: { type: 'svg', name: 'memoryCard' }, + desc: '经典的记忆翻牌游戏,翻开卡片寻找相同的图案,考验你的瞬间记忆力!', + url: '/tools/games/memory-card', + cate: '摸鱼小游戏', + isNew: true, + tags: ['免费', '新品'] + } ] }, { @@ -744,6 +753,16 @@ export function getToolsCate(): ToolCategory[] { cate: '实用查询', isNew: true, tags: ['免费', '新品'] + }, + { + id: 816, + title: '帮我决定', + logo: { type: 'svg', name: 'decisionMaker' }, + desc: '选择困难症福音!输入选项,让运气帮你做决定', + url: '/tools/daily/decision-maker', + cate: '实用查询', + isNew: true, + tags: ['免费', '新品'] } ] } @@ -1260,6 +1279,16 @@ export function getToolsCate(): ToolCategory[] { cate: '性格测试', tags: ['专业', '免费'], isNew: true + }, + { + id: 1216, + title: '色彩性格测试', + logo: { type: 'svg', name: 'colorTest' }, + desc: '探索你是红、蓝、白、黄哪种性格,了解你的核心动力和优势', + url: '/tools/psychology/color-test', + cate: '性格测试', + tags: ['免费'], + isNew: true } ] }, From 70954cb5de94556a50cf5598ad5f53519ef918c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Sat, 13 Dec 2025 17:31:15 +0800 Subject: [PATCH 10/45] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0Banner=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E4=B8=8E=E9=93=BE=E6=8E=A5=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=96=B0=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Common/Banner.vue | 157 +++++--- src/components/Home/Changelog.vue | 267 +++++++++++-- src/components/Tools/AI/AINews.vue | 2 + src/components/Tools/Calculation/BMR/BMR.vue | 179 +++++++++ .../Tools/Calculation/Discount/Discount.vue | 102 +++++ .../Calculation/Percentage/Percentage.vue | 200 ++++++++++ .../Tools/Daily/Breathing/Breathing.vue | 188 +++++++++ .../Tools/Daily/FlipClock/FlipClock.vue | 341 ++++++++++++++++ .../Tools/Daily/ScreenTest/ScreenTest.vue | 144 +++++++ .../Design/Glassmorphism/Glassmorphism.vue | 153 +++++++ .../Tools/Design/Gradient/Gradient.vue | 157 ++++++++ .../ImageCompressor/ImageCompressor.vue | 311 +++++++++++++++ .../Tools/Dev/CaseConverter/CaseConverter.vue | 135 +++++++ src/components/Tools/Dev/Cron/Cron.vue | 376 ++++++++++++++++++ .../Tools/Dev/KeyboardTest/KeyboardTest.vue | 131 ++++++ .../Tools/Dev/SqlFormat/SqlFormat.vue | 141 +++++++ src/components/Tools/Games/Gomoku/Gomoku.vue | 212 ++++++++++ .../Tools/Games/ReactionTest/ReactionTest.vue | 188 +++++++++ .../Tools/Games/TypingRain/TypingRain.vue | 48 ++- .../Tools/Games/TypingRain/wordData.ts | 50 +++ .../Tools/HotRanking/HotRanking.vue | 3 +- .../Tools/ImageColor/ImageColor.vue | 242 +++++++++++ .../Tools/ImageToBase64/ImageToBase64.vue | 186 +++++++++ .../Tools/LoremIpsum/LoremIpsum.vue | 125 ++++++ .../Tools/Web/MetaTags/MetaTags.vue | 180 +++++++++ src/components/Tools/WebInfo/WebInfo.vue | 7 + src/components/Tools/icons.ts | 85 ++++ src/components/Tools/tools.ts | 254 +++++++++++- src/router/router.ts | 212 +++++++++- src/services/rss-news.ts | 1 + src/store/modules/tools.ts | 16 + 31 files changed, 4698 insertions(+), 95 deletions(-) create mode 100644 src/components/Tools/Calculation/BMR/BMR.vue create mode 100644 src/components/Tools/Calculation/Discount/Discount.vue create mode 100644 src/components/Tools/Calculation/Percentage/Percentage.vue create mode 100644 src/components/Tools/Daily/Breathing/Breathing.vue create mode 100644 src/components/Tools/Daily/FlipClock/FlipClock.vue create mode 100644 src/components/Tools/Daily/ScreenTest/ScreenTest.vue create mode 100644 src/components/Tools/Design/Glassmorphism/Glassmorphism.vue create mode 100644 src/components/Tools/Design/Gradient/Gradient.vue create mode 100644 src/components/Tools/Design/ImageCompressor/ImageCompressor.vue create mode 100644 src/components/Tools/Dev/CaseConverter/CaseConverter.vue create mode 100644 src/components/Tools/Dev/Cron/Cron.vue create mode 100644 src/components/Tools/Dev/KeyboardTest/KeyboardTest.vue create mode 100644 src/components/Tools/Dev/SqlFormat/SqlFormat.vue create mode 100644 src/components/Tools/Games/Gomoku/Gomoku.vue create mode 100644 src/components/Tools/Games/ReactionTest/ReactionTest.vue create mode 100644 src/components/Tools/ImageColor/ImageColor.vue create mode 100644 src/components/Tools/ImageToBase64/ImageToBase64.vue create mode 100644 src/components/Tools/LoremIpsum/LoremIpsum.vue create mode 100644 src/components/Tools/Web/MetaTags/MetaTags.vue diff --git a/src/components/Common/Banner.vue b/src/components/Common/Banner.vue index a8e6882..738a78c 100644 --- a/src/components/Common/Banner.vue +++ b/src/components/Common/Banner.vue @@ -2,12 +2,15 @@ /** * @file Banner.vue * @description 广告横幅组件,用于展示广告内容 + * @copyright Tomda (https://www.tomda.top) + * @copyright UIED技术团队 (https://fsuied.com) + * @author UIED技术团队 * @createDate 2025-03-21 */ // 导入需要的组件和接口 import { ref } from 'vue' -import { Close } from '@element-plus/icons-vue' // 导入Close图标 +import { Promotion } from '@element-plus/icons-vue' // 广告数据 const bannerList = ref([ @@ -15,51 +18,86 @@ const bannerList = ref([ id: 1, link: 'https://fsuied.com/website-scmz.html', gradient: 'linear-gradient(to right, rgb(99, 102, 241) 0%, rgb(224, 231, 255) 35%, rgb(237, 242, 255) 45%, rgb(139, 92, 246) 100%)', - text: '无需代码 会打字就能轻松建网站 →' + text: '无需代码 会打字就能轻松建网站', + badge: '推荐' }, { id: 2, link: 'https://nf.video/mbx1u6/?gid=18', gradient: 'linear-gradient(to right, rgb(236, 72, 153) 0%, rgb(251, 231, 239) 35%, rgb(253, 242, 248) 45%, rgb(244, 114, 182) 100%)', - text: 'GPT-4o重回巅峰可生成逼真图文 →' + text: 'GPT-5.2重回巅峰 智能对话', + badge: '热门' + }, + { + id: 3, + link: 'https://www.trae.com.cn/?utm_source=advertising&utm_medium=uied_ug_cpa&utm_term=hw_trae_uied', + gradient: 'linear-gradient(to right, rgb(168, 85, 247) 0%, rgb(243, 232, 255) 35%, rgb(245, 243, 255) 45%, rgb(192, 132, 252) 100%)', + text: '免费AI编程工具 Trae - 智能编码助手', + badge: '新品' + }, + { + id: 4, + link: 'https://www.aippt.cn/?utm_type=Navweb&utm_source=bbdh&utm_page=aippt&utm_plan=ppt&utm_unit=AIPPT&utm_keyword=40471047', + gradient: 'linear-gradient(to right, rgb(16, 185, 129) 0%, rgb(209, 250, 229) 35%, rgb(236, 253, 245) 45%, rgb(52, 211, 153) 100%)', + text: '免费AI生成PPT - 一键生成演示文稿', + badge: '高效' + }, + { + id: 5, + link: 'https://universalbus.cn/?s=lPLG02aydo', + gradient: 'linear-gradient(to right, rgb(249, 115, 22) 0%, rgb(255, 237, 213) 35%, rgb(255, 247, 237) 45%, rgb(251, 146, 60) 100%)', + text: 'Adobe 正版全家桶可用AI', + badge: '特惠' + }, + { + id: 6, + link: 'https://universalbus.cn/?s=lPLG02aydo', + gradient: 'linear-gradient(to right, rgb(14, 165, 233) 0%, rgb(224, 242, 254) 35%, rgb(240, 249, 255) 45%, rgb(56, 189, 248) 100%)', + text: 'Gemini3 可用 nanobanana', + badge: '新品' } ]) - -// 是否显示广告 -const showBanner = ref(true) - -// 关闭广告 -const closeBanner = () => { - showBanner.value = false -} diff --git a/src/components/Home/Changelog.vue b/src/components/Home/Changelog.vue index e94e57f..a6732da 100644 --- a/src/components/Home/Changelog.vue +++ b/src/components/Home/Changelog.vue @@ -12,9 +12,9 @@ import { ref, onMounted, onUnmounted, watch, type ComponentPublicInstance } from * * @author Tomda * @createDate 2025-01-09 - * @lastUpdate 2025-12-12 12:00 - * @version Beta 2.4.3 - * @toolsCount 当前工具总数:179个 + * @lastUpdate 2025-12-13 18:00 + * @version Beta 2.4.8 + * @toolsCount 当前工具总数:194个 */ const tocItems = ref<{ id: string; version: string; date: string; title: string }[]>([]); @@ -243,7 +243,7 @@ onUnmounted(() => {
- 当前工具总数:179个 | 最后更新:2025-12-12 12:00 + 当前工具总数:194个 | 最后更新:2025-12-13 18:00
@@ -280,6 +280,221 @@ onUnmounted(() => {
+ +
+
+ 2.4.8 + 2025-12-13 18:00 +
+
+
+ 更新 + 实用开发与计算工具 +
+
+
    +
  • +
    新增工具
    +
    +
      +
    • SQL格式化:在线SQL代码格式化和美化工具,支持多种SQL方言。 +
    • +
    • 折扣计算器:快速计算打折后的价格和节省的金额,支持折扣率和减免金额。 +
    • +
    • CSS 渐变生成器:在线生成精美的 CSS + 线性渐变和径向渐变背景代码。 +
    • +
    • Meta 标签生成器:生成网页 SEO + 及社交媒体分享所需的 Meta 标签。 +
    • +
    +
    +
  • +
+
+
+
+ + +
+
+ 2.4.7 + 2025-12-13 16:00 +
+
+
+ 更新 + 设计规范优化与新工具 +
+
+
    +
  • +
    新增健康工具
    +
    +
      +
    • BMR + 基础代谢计算器:计算基础代谢率(BMR)和每日热量消耗(TDEE),科学管理身材。 +
    • +
    +
    +
  • +
  • +
    设计规范优化
    +
    +
      +
    • 优化了在线图片压缩工具的页面布局和视觉风格,使其与整体 UI 规范保持一致。
    • +
    • 优化了全屏翻页时钟的默认展示效果,增加了卡片容器和全屏切换动画。
    • +
    +
    +
  • +
+
+
+
+ + +
+
+ 2.4.6 + 2025-12-13 14:00 +
+
+
+ 更新 + 视觉与图片工具上新 +
+
+
    +
  • +
    新增工具
    +
    +
      +
    • 全屏翻页时钟:极简风格的翻页时钟,支持 + 12/24 小时制,适合作为桌面屏保。 +
    • +
    • 在线图片压缩:支持 + JPG/PNG/WEBP 格式图片压缩,可调节质量和尺寸,本地处理更安全。 +
    • +
    +
    +
  • +
  • +
    体验优化
    +
    +
      +
    • 优化了打字雨游戏的游戏区域高度,适配不同屏幕尺寸,提升游戏体验。
    • +
    +
    +
  • +
+
+
+
+ + +
+
+ 2.4.5 + 2025-12-13 12:00 +
+
+
+ 更新 + 前端开发工具上新 +
+
+
    +
  • +
    新增开发工具
    +
    +
      +
    • CSS 渐变生成器:在线生成精美的 CSS + 线性渐变和径向渐变背景代码。 +
    • +
    • Meta 标签生成器:生成网页 SEO + 及社交媒体分享所需的 Meta 标签,支持实时预览。 +
    • +
    +
    +
  • +
+
+
+
+ + +
+
+ 2.4.4 + 2025-12-13 10:00 +
+
+
+ 更新 + 开发、设计与生活工具上新 +
+
+
    +
  • +
    新增开发与设计工具
    +
    +
      +
    • CSS 玻璃拟态生成器:在线生成 + Glassmorphism 风格 CSS 代码。 +
    • +
    • 图片转 Base64:在线将图片转换为 + Base64 编码,支持一键复制。 +
    • +
    • 命名风格转换:支持 + Camel、Pascal、Snake、Kebab 等多种变量命名风格互转。 +
    • +
    • Lorem Ipsum + 生成器:快速生成中文、英文占位符文本。 +
    • +
    +
    +
  • +
  • +
    新增生活工具
    +
    +
      +
    • 图片主色调提取:上传图片自动提取主色调,生成配色方案。 +
    • +
    • 百分比计算器:在线百分比计算工具,支持计算占比、数值计算、增长率等。 +
    • +
    +
    +
  • +
  • +
    新增测试工具
    +
    +
      +
    • 键盘测试:在线检测键盘按键是否正常,支持全键位检测。 +
    • +
    +
    +
  • +
+
+
+
+
@@ -297,7 +512,7 @@ onUnmounted(() => {
新增生活常用工具
    -
  • 帮我决定:选择困难症福音,输入选项,让运气帮你做决定。
@@ -307,7 +522,7 @@ onUnmounted(() => {
新增潜能测试
    -
  • 色彩性格测试:基于哈特曼性格色彩密码,探索你的核心动力和性格优势。
@@ -343,7 +558,7 @@ onUnmounted(() => {
新增小游戏
    -
  • 记忆翻牌:考验记忆力的翻牌配对游戏,支持 4x4 和 6x6 两种难度。
  • @@ -380,10 +595,10 @@ onUnmounted(() => {
    新增摸鱼工具
      -
    • 电子木鱼:在线敲木鱼,积攒功德,净化心灵。
    • -
    • 2048:经典的数字合成游戏,挑战合成2048。
    @@ -420,10 +635,10 @@ onUnmounted(() => {
    新增经典小游戏
      -
    • 贪吃蛇:经典怀旧游戏,控制小蛇吃食物变长,挑战反应速度与策略规划。
    • -
    • 扫雷:Windows 经典再现,提供初级、中级、高级三种难度,支持右键插旗标记,锻炼逻辑推理能力。
    • @@ -452,11 +667,11 @@ onUnmounted(() => {
      新增打字雨游戏
        -
      • 打字雨 (中文版):经典打字游戏,支持中文词库,锻炼拼音输入速度。
      • -
      • 打字雨 (英文版):Type the falling words before they hit the ground! 锻炼英文打字速度。
      • @@ -487,10 +702,10 @@ onUnmounted(() => {
        新增实用工具
          -
        • 亲戚称呼计算器:解决过年走亲戚不知如何称呼的尴尬,支持互查,逢年过节必备神器。
        • -
        • Base64转换工具:支持文本与图片的Base64编码转换,支持UTF-8字符集与常见图片格式。
        @@ -590,19 +805,19 @@ onUnmounted(() => {
        新增5款效率计算器
          -
        • 房贷计算器:支持商业贷款、公积金贷款及组合贷款计算,提供等额本息与等额本金两种还款方式对比。
        • -
        • 房贷利率调整计算器:快速计算LPR利率调整前后的月供变化与利息节省情况。
        • -
        • 投资收益计算器:支持复利计算与定投收益预测,辅助制定长期理财规划。
        • -
        • 五险一金计算器:依据2025最新政策,精准计算个人应缴社保公积金及税后收入。
        • -
        • 温度转换器:支持摄氏度、华氏度、开尔文温标的实时双向转换。
        @@ -669,13 +884,13 @@ onUnmounted(() => {
        新增数据图表工具
          -
        • 雷达图:支持多维数据对比分析,适用于能力评估、绩效分析等场景。
        • -
        • 漏斗图:支持转化率分析,适用于销售漏斗、用户行为路径等场景。
        • -
        • 仪表盘:支持进度展示与完成率分析,适用于KPI监控、目标追踪等场景。
        @@ -4007,15 +4222,15 @@ body { /* Firefox */ -webkit-overflow-scrolling: touch; } - /* Transitions */ .fade-enter-active, .fade-leave-active { -transition: opacity 0.3s ease; + transition: opacity 0.3s ease; } .fade-enter-from, .fade-leave-to { -opacity: 0; + opacity: 0; } + diff --git a/src/components/Tools/AI/AINews.vue b/src/components/Tools/AI/AINews.vue index b1ac6d6..4371c28 100644 --- a/src/components/Tools/AI/AINews.vue +++ b/src/components/Tools/AI/AINews.vue @@ -1,6 +1,8 @@ diff --git a/src/components/Tools/Calculation/BMR/BMR.vue b/src/components/Tools/Calculation/BMR/BMR.vue new file mode 100644 index 0000000..93519b8 --- /dev/null +++ b/src/components/Tools/Calculation/BMR/BMR.vue @@ -0,0 +1,179 @@ + + + diff --git a/src/components/Tools/Calculation/Discount/Discount.vue b/src/components/Tools/Calculation/Discount/Discount.vue new file mode 100644 index 0000000..bef5df6 --- /dev/null +++ b/src/components/Tools/Calculation/Discount/Discount.vue @@ -0,0 +1,102 @@ +/** + * @copyright Tomda (https://www.tomda.top) + * @copyright UIED技术团队 (https://fsuied.com) + * @author UIED技术团队 + * @createDate 2025-12-13 + */ + + + + \ No newline at end of file diff --git a/src/components/Tools/Calculation/Percentage/Percentage.vue b/src/components/Tools/Calculation/Percentage/Percentage.vue new file mode 100644 index 0000000..c1dd18e --- /dev/null +++ b/src/components/Tools/Calculation/Percentage/Percentage.vue @@ -0,0 +1,200 @@ + + + + + diff --git a/src/components/Tools/Daily/Breathing/Breathing.vue b/src/components/Tools/Daily/Breathing/Breathing.vue new file mode 100644 index 0000000..d440fe6 --- /dev/null +++ b/src/components/Tools/Daily/Breathing/Breathing.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/src/components/Tools/Daily/FlipClock/FlipClock.vue b/src/components/Tools/Daily/FlipClock/FlipClock.vue new file mode 100644 index 0000000..701d5d7 --- /dev/null +++ b/src/components/Tools/Daily/FlipClock/FlipClock.vue @@ -0,0 +1,341 @@ + + + + + diff --git a/src/components/Tools/Daily/ScreenTest/ScreenTest.vue b/src/components/Tools/Daily/ScreenTest/ScreenTest.vue new file mode 100644 index 0000000..d60b00d --- /dev/null +++ b/src/components/Tools/Daily/ScreenTest/ScreenTest.vue @@ -0,0 +1,144 @@ + + + diff --git a/src/components/Tools/Design/Glassmorphism/Glassmorphism.vue b/src/components/Tools/Design/Glassmorphism/Glassmorphism.vue new file mode 100644 index 0000000..7468bfd --- /dev/null +++ b/src/components/Tools/Design/Glassmorphism/Glassmorphism.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/src/components/Tools/Design/Gradient/Gradient.vue b/src/components/Tools/Design/Gradient/Gradient.vue new file mode 100644 index 0000000..9f6ad6d --- /dev/null +++ b/src/components/Tools/Design/Gradient/Gradient.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/src/components/Tools/Design/ImageCompressor/ImageCompressor.vue b/src/components/Tools/Design/ImageCompressor/ImageCompressor.vue new file mode 100644 index 0000000..df303a0 --- /dev/null +++ b/src/components/Tools/Design/ImageCompressor/ImageCompressor.vue @@ -0,0 +1,311 @@ + + + + + diff --git a/src/components/Tools/Dev/CaseConverter/CaseConverter.vue b/src/components/Tools/Dev/CaseConverter/CaseConverter.vue new file mode 100644 index 0000000..d5dec5e --- /dev/null +++ b/src/components/Tools/Dev/CaseConverter/CaseConverter.vue @@ -0,0 +1,135 @@ + + + diff --git a/src/components/Tools/Dev/Cron/Cron.vue b/src/components/Tools/Dev/Cron/Cron.vue new file mode 100644 index 0000000..9d73cb2 --- /dev/null +++ b/src/components/Tools/Dev/Cron/Cron.vue @@ -0,0 +1,376 @@ + + + diff --git a/src/components/Tools/Dev/KeyboardTest/KeyboardTest.vue b/src/components/Tools/Dev/KeyboardTest/KeyboardTest.vue new file mode 100644 index 0000000..0e7343e --- /dev/null +++ b/src/components/Tools/Dev/KeyboardTest/KeyboardTest.vue @@ -0,0 +1,131 @@ + + + diff --git a/src/components/Tools/Dev/SqlFormat/SqlFormat.vue b/src/components/Tools/Dev/SqlFormat/SqlFormat.vue new file mode 100644 index 0000000..817261d --- /dev/null +++ b/src/components/Tools/Dev/SqlFormat/SqlFormat.vue @@ -0,0 +1,141 @@ + + + \ No newline at end of file diff --git a/src/components/Tools/Games/Gomoku/Gomoku.vue b/src/components/Tools/Games/Gomoku/Gomoku.vue new file mode 100644 index 0000000..f51f0b5 --- /dev/null +++ b/src/components/Tools/Games/Gomoku/Gomoku.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/src/components/Tools/Games/ReactionTest/ReactionTest.vue b/src/components/Tools/Games/ReactionTest/ReactionTest.vue new file mode 100644 index 0000000..56a7867 --- /dev/null +++ b/src/components/Tools/Games/ReactionTest/ReactionTest.vue @@ -0,0 +1,188 @@ + + + diff --git a/src/components/Tools/Games/TypingRain/TypingRain.vue b/src/components/Tools/Games/TypingRain/TypingRain.vue index 3ec8030..010f937 100644 --- a/src/components/Tools/Games/TypingRain/TypingRain.vue +++ b/src/components/Tools/Games/TypingRain/TypingRain.vue @@ -25,7 +25,7 @@
        + class="typing-rain-container relative w-full overflow-y-auto bg-gray-900 flex flex-col items-center justify-center font-sans text-white select-none rounded-xl py-8 min-h-[600px] h-[85vh]">
        @@ -35,7 +35,7 @@
        -
        +
        @@ -137,6 +137,24 @@ }}

        + +
        + +
        + +
        +
        +
        +
        + +
        +
        + + + diff --git a/src/components/Tools/LoremIpsum/LoremIpsum.vue b/src/components/Tools/LoremIpsum/LoremIpsum.vue new file mode 100644 index 0000000..4cc1d2f --- /dev/null +++ b/src/components/Tools/LoremIpsum/LoremIpsum.vue @@ -0,0 +1,125 @@ + + + diff --git a/src/components/Tools/Web/MetaTags/MetaTags.vue b/src/components/Tools/Web/MetaTags/MetaTags.vue new file mode 100644 index 0000000..d4c7a4b --- /dev/null +++ b/src/components/Tools/Web/MetaTags/MetaTags.vue @@ -0,0 +1,180 @@ + + + diff --git a/src/components/Tools/WebInfo/WebInfo.vue b/src/components/Tools/WebInfo/WebInfo.vue index fa16dae..97e5377 100644 --- a/src/components/Tools/WebInfo/WebInfo.vue +++ b/src/components/Tools/WebInfo/WebInfo.vue @@ -1,3 +1,10 @@ +/** + * @copyright Tomda (https://www.tomda.top) + * @copyright UIED技术团队 (https://fsuied.com) + * @author UIED技术团队 + * @createDate 2025-12-13 + */ + - {{ category.title }} @@ -454,7 +431,7 @@ onMounted(() => { 剪辑工具 - {{ category.title }} @@ -485,7 +462,7 @@ onMounted(() => { 开发工具 - {{ category.title }} @@ -511,7 +488,7 @@ onMounted(() => { 摸鱼工具 - {{ category.title }} @@ -532,7 +509,7 @@ onMounted(() => { 效率工具 - {{ category.title }} diff --git a/src/router/index.ts b/src/router/index.ts index 36ce3b9..0ba32d3 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -20,14 +20,14 @@ const router = createRouter({ }) // _form: '_'表示占位变量,可以不被使用 -router.beforeEach((to, from, next) => { - // 处理标题 - if (to.meta.title && to.meta.title != '') { - let oldTitle = document.title - document.title = to.meta.title + '-' + oldTitle - } - next() -}) +// router.beforeEach((to, from, next) => { +// // 处理标题 +// if (to.meta.title && to.meta.title != '') { +// let oldTitle = document.title +// document.title = to.meta.title + '-' + oldTitle +// } +// next() +// }) //路由后置卫士 router.afterEach((to) => { diff --git a/src/router/router.ts b/src/router/router.ts index e82644d..6b86242 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -15,7 +15,7 @@ import BackendTest from '../components/Tools/BackendTest/BackendTest.vue' // 根据环境变量判断使用的 base 路径 const base = import.meta.env.PROD ? '/' : '/' -export const constantRoute = [ +export const constantRoute: RouteRecordRaw[] = [ //首页 { path: '/', @@ -150,13 +150,8 @@ export const constantRoute = [ }, { path: '/tools/ai/analysis-report', - component: () => import('@/components/Tools/AI/Writing/AnalysisReport.vue'), - name: 'analysisReport', - meta: { - title: "分析报告", - keywords: '分析报告,数据分析,市场分析,问题分析,商业报告', - description: '免费在线AI分析报告生成工具,智能生成专业的数据分析、市场分析或问题分析报告,提供深度洞察', - } + redirect: '/tools/ai/analysis/analysis-report', + name: 'analysisReportRedirect' }, { path: '/tools/ai/weekly-summary', @@ -378,6 +373,166 @@ export const constantRoute = [ description: '智能生成专业简历,优化工作经历和技能描述,提升求职成功率', } }, + { + path: '/tools/ai/analysis/research-report', + component: () => import('@/components/Tools/AI/Analysis/ResearchReport.vue'), + name: 'aiResearchReport', + meta: { + title: "研究报告", + keywords: 'AI研究报告,深度研究,学术研究,商业研究,报告生成', + description: '智能生成深度研究报告,涵盖研究背景、方法、结果与结论,助力学术与商业研究', + } + }, + { + path: '/tools/ai/analysis/analysis-report', + component: () => import('@/components/Tools/AI/Analysis/AnalysisReport.vue'), + name: 'aiAnalysisReportNew', + meta: { + title: "分析报告", + keywords: 'AI分析报告,数据分析,问题分析,趋势分析,深度洞察', + description: '智能生成各类分析报告,深度剖析问题成因、现状与趋势,提供专业见解', + } + }, + { + path: '/tools/ai/analysis/activity-plan', + component: () => import('@/components/Tools/AI/Analysis/ActivityPlan.vue'), + name: 'aiActivityPlan', + meta: { + title: "活动方案", + keywords: 'AI活动策划,活动方案,活动计划,创意策划,执行方案', + description: '智能生成创意活动方案,包含流程设计、预算规划与执行细节,确保活动精彩呈现', + } + }, + { + path: '/tools/ai/analysis/business-plan', + component: () => import('@/components/Tools/AI/Analysis/BusinessPlan.vue'), + name: 'aiBusinessPlan', + meta: { + title: "商业计划书", + keywords: 'AI商业计划书,BP写作,创业计划,融资计划,项目计划', + description: '智能撰写专业商业计划书,涵盖市场分析、商业模式、运营策略与财务预测,助力融资成功', + } + }, + { + path: '/tools/ai/analysis/survey-report', + component: () => import('@/components/Tools/AI/Analysis/SurveyReport.vue'), + name: 'aiSurveyReport', + meta: { + title: "调研报告", + keywords: 'AI调研报告,市场调研,用户调研,实地调研,数据分析', + description: '智能生成实地调研报告,整理调研数据,提炼核心发现,支持决策制定', + } + }, + { + path: '/tools/ai/analysis/industry-report', + component: () => import('@/components/Tools/AI/Analysis/IndustryReport.vue'), + name: 'aiIndustryReport', + meta: { + title: "行业报告", + keywords: 'AI行业报告,行业分析,市场趋势,竞争格局,产业研究', + description: '智能生成行业深度分析报告,洞察市场规模、竞争格局与未来趋势', + } + }, + { + path: '/tools/ai/analysis/feasibility-study', + component: () => import('@/components/Tools/AI/Analysis/FeasibilityStudy.vue'), + name: 'aiFeasibilityStudy', + meta: { + title: "可行性研究报告", + keywords: '可行性研究报告,项目可行性,投资分析,效益评估,风险分析', + description: '智能生成专业的可行性研究报告,包含市场分析、建设方案、投资估算和效益分析', + } + }, + { + path: '/tools/ai/analysis/project-application', + component: () => import('@/components/Tools/AI/Analysis/ProjectApplication.vue'), + name: 'aiProjectApplication', + meta: { + title: "立项申请报告", + keywords: '立项申请报告,项目立项,立项建议书,项目申请,立项审批', + description: '智能生成项目立项申请报告,阐述项目必要性、可行性和实施计划,助力项目审批', + } + }, + { + path: '/tools/ai/analysis/pest', + component: () => import('@/components/Tools/AI/Analysis/PestAnalysis.vue'), + name: 'aiPEST', + meta: { + title: "PEST分析", + keywords: 'PEST分析,宏观环境分析,政策分析,经济分析,社会分析,技术分析', + description: '智能进行PEST分析,深度解读政治、经济、社会和技术环境对项目或企业的影响', + } + }, + { + path: '/tools/ai/analysis/swot', + component: () => import('@/components/Tools/AI/Analysis/SwotAnalysis.vue'), + name: 'aiSWOT', + meta: { + title: "SWOT分析", + keywords: 'SWOT分析,战略分析,优势劣势,机会威胁,企业战略', + description: '智能进行SWOT分析,全面评估优势、劣势、机会和威胁,制定科学的发展战略', + } + }, + { + path: '/tools/ai/analysis/transport-plan', + component: () => import('@/components/Tools/AI/Analysis/TransportPlan.vue'), + name: 'aiTransportPlan', + meta: { + title: "运输方案", + keywords: '运输方案,物流方案,运输计划,配送方案,物流规划', + description: '智能生成高效的运输方案,规划最佳路线、运输方式和成本预算,提升物流效率', + } + }, + { + path: '/tools/ai/analysis/situation-report', + component: () => import('@/components/Tools/AI/Analysis/SituationReport.vue'), + name: 'aiSituationReport', + meta: { + title: "情况报告", + keywords: '情况报告,情况说明,突发事件报告,工作情况,调查报告', + description: '智能生成各类情况报告,客观陈述事实经过,分析原因并提出处理建议', + } + }, + { + path: '/tools/ai/analysis/seven-s', + component: () => import('@/components/Tools/AI/Analysis/BostonAnalysis.vue'), + name: 'aiSevenS', + meta: { + title: "波士顿7S分析", + keywords: '7S分析,麦肯锡7S,组织分析,企业管理,战略实施', + description: '智能进行麦肯锡7S模型分析,从战略、结构、制度等七个维度全面诊断企业组织状况', + } + }, + { + path: '/tools/ai/analysis/marketing-4p', + component: () => import('@/components/Tools/AI/Analysis/Marketing4p.vue'), + name: 'aiMarketing4P', + meta: { + title: "4P营销分析", + keywords: '4P营销,营销策略,产品价格,渠道推广,市场营销', + description: '智能进行4P营销理论分析,制定产品、价格、渠道和推广策略,提升市场竞争力', + } + }, + { + path: '/tools/ai/analysis/industry-consultant', + component: () => import('@/components/Tools/AI/Analysis/IndustryConsultant.vue'), + name: 'aiIndustryConsultant', + meta: { + title: "产业顾问", + keywords: '产业顾问,产业分析,行业咨询,产业规划,专家建议', + description: '智能扮演资深产业顾问,提供专业的行业洞察、发展建议和决策支持', + } + }, + { + path: '/tools/ai/analysis/startup-ideas', + component: () => import('@/components/Tools/AI/Analysis/InnovationIdea.vue'), + name: 'aiStartupIdeas', + meta: { + title: "创新创业金点子", + keywords: '创业点子,创新思维,商业创意,创业项目,创业灵感', + description: '智能生成创新创业金点子,结合市场趋势和资源优势,提供具有潜力的商业创意', + } + }, { path: '/tools/ai/office/work-plan', component: () => import('@/components/Tools/AI/Office/WorkPlan.vue'), @@ -528,6 +683,127 @@ export const constantRoute = [ description: '智能辅助生成毕业论文初稿,包含摘要、正文和参考文献,助力学术写作', } }, + // AI学生助手 + { + path: '/tools/ai/student/internship-comments', + component: () => import('@/components/Tools/AI/Student/InternshipComments.vue'), + name: 'aiInternshipComments', + meta: { + title: "实习评语", + keywords: 'AI实习评语,实习评价,学生评语,AI写作', + description: '免费在线AI实习评语生成工具,智能生成专业的实习评价内容', + } + }, + { + path: '/tools/ai/student/research-report', + component: () => import('@/components/Tools/AI/Student/ResearchReport.vue'), + name: 'aiStudentResearchReport', + meta: { + title: "研究报告", + keywords: 'AI研究报告,课题研究,学术报告,AI写作', + description: '免费在线AI研究报告生成工具,智能生成高质量的研究报告内容', + } + }, + { + path: '/tools/ai/student/internship-weekly', + component: () => import('@/components/Tools/AI/Student/InternshipWeekly.vue'), + name: 'aiInternshipWeekly', + meta: { + title: "实习周记", + keywords: 'AI实习周记,实习日志,周记生成,AI写作', + description: '免费在线AI实习周记生成工具,智能记录实习期间的工作内容和感悟', + } + }, + { + path: '/tools/ai/student/internship-summary', + component: () => import('@/components/Tools/AI/Student/InternshipSummary.vue'), + name: 'aiStudentInternshipSummary', + meta: { + title: "实习总结", + keywords: 'AI实习总结,实习汇报,总结报告,AI写作', + description: '免费在线AI实习总结生成工具,智能生成结构完整的实习总结报告', + } + }, + { + path: '/tools/ai/student/social-practice', + component: () => import('@/components/Tools/AI/Student/SocialPractice.vue'), + name: 'aiSocialPractice', + meta: { + title: "暑假社会实践心得", + keywords: 'AI社会实践,实践心得,暑假实践,AI写作', + description: '免费在线AI社会实践心得生成工具,智能生成深刻的实践感悟和体会', + } + }, + { + path: '/tools/ai/student/practice-report', + component: () => import('@/components/Tools/AI/Student/PracticeReport.vue'), + name: 'aiStudentPracticeReport', + meta: { + title: "实践报告", + keywords: 'AI实践报告,社会实践,项目报告,AI写作', + description: '免费在线AI实践报告生成工具,智能生成规范的实践活动报告', + } + }, + { + path: '/tools/ai/student/analysis-report', + component: () => import('@/components/Tools/AI/Student/AnalysisReport.vue'), + name: 'aiStudentAnalysisReport', + meta: { + title: "分析报告", + keywords: 'AI分析报告,案例分析,SWOT分析,AI写作', + description: '免费在线AI分析报告生成工具,智能生成各类深度分析报告', + } + }, + { + path: '/tools/ai/student/interview-guide', + component: () => import('@/components/Tools/AI/Student/InterviewGuide.vue'), + name: 'aiInterviewGuide', + meta: { + title: "面试指南", + keywords: 'AI面试指南,面试技巧,面试问题,AI写作', + description: '免费在线AI面试指南生成工具,智能提供针对性的面试建议和问答', + } + }, + { + path: '/tools/ai/student/internship-experience', + component: () => import('@/components/Tools/AI/Student/InternshipExperience.vue'), + name: 'aiInternshipExperience', + meta: { + title: "实习体验报告", + keywords: 'AI实习体验,实习感受,职场体验,AI写作', + description: '免费在线AI实习体验报告生成工具,智能生成真实的实习生活体验记录', + } + }, + { + path: '/tools/ai/student/internship-report', + component: () => import('@/components/Tools/AI/Student/InternshipReport.vue'), + name: 'aiStudentInternshipReport', + meta: { + title: "实习报告", + keywords: 'AI实习报告,实习结业,实习证明,AI写作', + description: '免费在线AI实习报告生成工具,智能生成符合要求的正式实习报告', + } + }, + { + path: '/tools/ai/student/resume-creation', + component: () => import('@/components/Tools/AI/Student/ResumeCreation.vue'), + name: 'aiStudentResumeCreation', + meta: { + title: "简历制作", + keywords: 'AI简历,简历生成,求职简历,AI写作', + description: '免费在线AI简历内容生成工具,智能生成专业的简历各模块内容', + } + }, + { + path: '/tools/ai/student/activity-plan', + component: () => import('@/components/Tools/AI/Student/ActivityPlan.vue'), + name: 'aiStudentActivityPlan', + meta: { + title: "活动方案", + keywords: 'AI活动方案,校园活动,策划书,AI写作', + description: '免费在线AI活动方案生成工具,智能生成创意十足的活动策划方案', + } + }, { path: '/tools/image-to-webp', component: () => import('@/components/Tools/ImageToWebp/ImageToWebp.vue'), @@ -623,7 +899,7 @@ export const constantRoute = [ component: () => import('@/components/Tools/PdfMerge/index.vue'), name: 'pdfMerge', meta: { - title: "免费在线PDF合并工具", + title: "PDF合并", keywords: 'PDF合并,PDF合并工具,在线PDF合并,免费PDF合并,PDF文件合并,合并PDF', description: '免费在线PDF合并工具,支持多个PDF文件合并,无需上传至云端,本地处理更安全。支持调整合并顺序。' } @@ -633,7 +909,7 @@ export const constantRoute = [ component: () => import('@/components/Tools/PdfSplit/index.vue'), name: 'pdfSplit', meta: { - title: '免费在线PDF分割工具', + title: 'PDF分割', keywords: 'PDF分割,PDF拆分,PDF分页,在线PDF分割,免费PDF分割,PDF提取页面', description: '免费在线PDF分割工具,支持将PDF拆分为单页,提取指定页面,批量处理多个文件,本地处理更安全。' } @@ -663,7 +939,7 @@ export const constantRoute = [ component: () => import('@/components/Tools/PdfCompress/index.vue'), name: 'pdfCompress', meta: { - title: "免费PDF压缩工具", + title: "PDF压缩", keywords: 'PDF压缩,PDF文件压缩,在线PDF压缩,免费PDF压缩,缩小PDF', description: '在线压缩PDF文件大小,支持批量处理,本地压缩更安全,适合邮件发送和文件上传,保持良好画质。' } @@ -715,7 +991,7 @@ export const constantRoute = [ meta: { title: "PDF文本提取", keywords: 'PDF文本提取,PDF转TXT,PDF复制文本,PDF文字识别,提取PDF内容', - description: '免费在线提取PDF文件中的文本内容,支持复制和导出TXT,本地处理更安全。' + description: '免费在线提取PDF文件中的文本内容,支持复制和导出TXT,本地处理更安全。' } }, { @@ -818,6 +1094,26 @@ export const constantRoute = [ description: '在线从视频中提取音频,支持导出为 WAV 格式。' } }, + { + path: '/tools/design/font-copyright', + component: () => import('@/components/Tools/Design/FontCopyright.vue'), + name: 'fontCopyright', + meta: { + title: "字体版权查询", + keywords: '字体版权,商用字体,免费字体,字体查询', + description: '查询字体版权信息,确认是否可以免费商用,避免版权纠纷。' + } + }, + { + path: '/tools/life/countdown', + component: () => import('@/components/Tools/Life/CountdownDay.vue'), + name: 'countdownDay', + meta: { + title: "摸鱼倒数日", + keywords: '摸鱼,倒数日,节假日,下班倒计时,周末倒计时', + description: '工作再忙,也别忘了期待假期。实时查看距离周末和节假日还有多久。' + } + }, { path: '/tools/video/mute', component: () => import('@/components/Tools/Video/VideoMute/VideoMute.vue'), @@ -960,13 +1256,8 @@ export const constantRoute = [ }, { path: '/tools/media/qrcode-generator', - component: () => import('@/components/Tools/Media/QrcodeGenerator/QrcodeGenerator.vue'), - name: 'qrcodeGenerator', - meta: { - title: "二维码生成器", - keywords: '二维码生成,在线二维码,QR Code Generator,自定义二维码', - description: '在线生成自定义二维码,支持设置颜色、尺寸、容错率,可下载 PNG 图片。' - } + redirect: '/tools/qrcode', + name: 'qrcodeGeneratorRedirect' }, { path: '/tools/dev/url-encoder', @@ -1862,6 +2153,16 @@ export const constantRoute = [ description: '智能推荐中英文字体搭配方案,提供字体预览', } }, + { + path: '/tools/design/font-copyright', + component: () => import('@/components/Tools/Design/FontCopyright.vue'), + name: 'fontCopyright', + meta: { + title: "字体版权查询", + keywords: '字体版权查询,商用字体查询,免费商用字体,字体侵权检测', + description: '免费在线字体版权查询工具,快速查询字体是否可以免费商用,避免版权纠纷', + } + }, { path: '/tools/design/ui-spec', component: () => import('@/components/Tools/Design/UiSpec.vue'), @@ -2368,7 +2669,7 @@ export const constantRoute = [ name: 'AINews', component: () => import('@/components/Tools/AI/AINews.vue'), meta: { - title: 'AI实时快讯 - UIED-Tools', + title: 'AI实时快讯', keywords: 'AI新闻,科技资讯,AI快讯,人工智能新闻', description: '实时展示最新AI科技资讯,及时了解人工智能领域的最新动态和发展趋势。' } @@ -2701,6 +3002,16 @@ export const constantRoute = [ description: '免费天气预报查询,支持全球城市,提供实时温度、湿度、风速等详细气象信息', } }, + { + path: '/tools/daily/car-price', + component: () => import('@/components/Tools/Life/CarPrice.vue'), + name: 'carPrice', + meta: { + title: "车辆价格查询", + keywords: '车辆价格查询,汽车报价,新车价格,经销商报价,汽车配置', + description: '快速查询车辆指导价、经销商报价及配置信息', + } + }, { path: '/tools/daily/bmi', component: () => import('@/components/Tools/Daily/Bmi/index.vue'), diff --git a/src/store/modules/tools.ts b/src/store/modules/tools.ts index 0779576..c7139e5 100644 --- a/src/store/modules/tools.ts +++ b/src/store/modules/tools.ts @@ -1,30 +1,13 @@ import { defineStore } from 'pinia' import { getToolsCate } from '../../components/Tools/tools' import { getWebInfo } from '../../api/webinfo' +import type { Tool, ToolCategory, ToolSubCategory } from '@/types/tools' -export interface Tool { - id: number - title: string - logo: string | { type: 'svg', name: string } - desc: string - url: string +interface ToolInfoQuery { + id?: number + title?: string + route?: string cateId?: number - cate?: string - children?: Tool[] - isExternal?: boolean -} - -export interface ToolSubCategory { - id: number - title: string - list: Tool[] -} - -export interface ToolCategory { - id: number - title: string - icon?: string - list: ToolSubCategory[] } interface State { @@ -138,8 +121,8 @@ export const useToolsStore = defineStore('tools', { }, { id: 1007, - title: "GPT-5.0", - desc: "最新版GPT-5.0智能对话工具", + title: "GPT-5.2", + desc: "最新版GPT-5.2智能对话工具", url: "https://nf.video/oemcwv/?gid=18", logo: { type: 'svg', name: 'code' }, cate: "热门工具", @@ -177,6 +160,37 @@ export const useToolsStore = defineStore('tools', { this.webInfo = {} } }, + async getToolInfo(params: ToolInfoQuery) { + try { + if (!this.cates.length) { + await this.getToolCate() + } + const routeValue = params.route?.trim() + const toolId = params.id + const titleValue = params.title?.trim() + + const allTools = this.toolsList() + const matchedTool = allTools.find(tool => { + if (routeValue) { + return tool.url === routeValue + } + if (typeof toolId === 'number') { + return tool.id === toolId + } + if (titleValue) { + return tool.title === titleValue + } + return false + }) + + this.toolInfo = matchedTool || null + return this.toolInfo + } catch (error) { + console.error('获取工具详情失败:', error) + this.toolInfo = null + return null + } + }, async getToolCate() { try { // 使用 tools.ts 中定义的完整工具列表数据 diff --git a/src/types/tools.ts b/src/types/tools.ts index 8db970e..0b7a28d 100644 --- a/src/types/tools.ts +++ b/src/types/tools.ts @@ -1,6 +1,7 @@ export interface ToolsReqData { id?: number title?: string + cateId?: number category?: string page?: number pageSize?: number @@ -16,15 +17,34 @@ export interface Tool { cate?: string isExternal?: boolean releaseDate?: string + tags?: string[] + icon?: string + isNew?: boolean + gradient?: string + badge?: string + text?: string + children?: Tool[] +} + +export interface ToolSubCategory { + id: number + title: string + list: Tool[] } export interface ToolCategory { id: number title: string - tools: Tool[] + icon?: string + list: ToolSubCategory[] } export interface RecommendTool extends Tool { cateId: number cate: string } + +export interface ToolsFilterParams { + cateId: number + title: string +} diff --git a/src/utils/echarts.ts b/src/utils/echarts.ts index dedbbd3..21de187 100644 --- a/src/utils/echarts.ts +++ b/src/utils/echarts.ts @@ -39,9 +39,9 @@ export function toEchartsData(data) { /** * 转换成echarts使用的数据 - 适用于饼图 - * - * @param data - * @returns + * + * @param data + * @returns */ export function toEchartsPieData(data) { let tmpArr: Array = [] @@ -62,8 +62,8 @@ export function toEchartsPieData(data) { /** * 数据格式转换 - 根据type转换格式 * 对象格式{name: '', value: ''}; 列格式: nameArr = [], valueArr = [] - * @param data - * @returns + * @param data + * @returns */ export function tranObjAndColumn(data, type = 'toObj') { let returnData = [] as any[]; @@ -130,23 +130,23 @@ export default EchartsUtils /** -1: { - cells: { - 0: { text: 'testingtesttestetst' }, - 2: { text: 'testing' }, - }, -}, -2: { - cells: { - 0: { text: 'render', style: 0 }, - 1: { text: 'Hello' }, - 2: { text: 'haha', merge: [1, 1] }, - } -}, -8: { - cells: { - 8: { text: 'border test', style: 0 }, - } -} +1: { + cells: { + 0: { text: 'testingtesttestetst' }, + 2: { text: 'testing' }, + }, +}, +2: { + cells: { + 0: { text: 'render', style: 0 }, + 1: { text: 'Hello' }, + 2: { text: 'haha', merge: [1, 1] }, + } +}, +8: { + cells: { + 8: { text: 'border test', style: 0 }, + } +} - */ \ No newline at end of file + */ diff --git a/src/utils/verify.ts b/src/utils/verify.ts index f203d4b..b710f96 100644 --- a/src/utils/verify.ts +++ b/src/utils/verify.ts @@ -42,6 +42,11 @@ export function isHexadecimal(data: string): boolean { return /^([0-9a-fA-F]+)$/g.test(data) ? true : false; } +export const wechatVerifyConfig = { + password: 'uied2026', + maxFreeUsage: 5 +} + const VerifyUtils = { isIp, isBinary, @@ -50,4 +55,4 @@ const VerifyUtils = { isHexadecimal } -export default VerifyUtils \ No newline at end of file +export default VerifyUtils From 22779d9d43c02e292d4fead6c5d2c7c50cb9220f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Tue, 17 Mar 2026 09:30:39 +0800 Subject: [PATCH 18/45] chore: sync deps, tsconfig, and project auxiliary files --- .agents/skills/frontend-design/LICENSE.txt | 177 +++++++++++++ .agents/skills/frontend-design/SKILL.md | 42 +++ development-log.md | 58 +++++ docs/development-log.md | 0 package-lock.json | 281 +++++++++++++-------- package.json | 16 +- pnpm-lock.yaml | 88 ++++++- tsconfig.json | 9 +- tsconfig.node.json | 6 +- 9 files changed, 550 insertions(+), 127 deletions(-) create mode 100644 .agents/skills/frontend-design/LICENSE.txt create mode 100644 .agents/skills/frontend-design/SKILL.md create mode 100644 development-log.md create mode 100644 docs/development-log.md diff --git a/.agents/skills/frontend-design/LICENSE.txt b/.agents/skills/frontend-design/LICENSE.txt new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/.agents/skills/frontend-design/LICENSE.txt @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/.agents/skills/frontend-design/SKILL.md b/.agents/skills/frontend-design/SKILL.md new file mode 100644 index 0000000..5be498e --- /dev/null +++ b/.agents/skills/frontend-design/SKILL.md @@ -0,0 +1,42 @@ +--- +name: frontend-design +description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics. +license: Complete terms in LICENSE.txt +--- + +This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices. + +The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints. + +## Design Thinking + +Before coding, understand the context and commit to a BOLD aesthetic direction: +- **Purpose**: What problem does this interface solve? Who uses it? +- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction. +- **Constraints**: Technical requirements (framework, performance, accessibility). +- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember? + +**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity. + +Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is: +- Production-grade and functional +- Visually striking and memorable +- Cohesive with a clear aesthetic point-of-view +- Meticulously refined in every detail + +## Frontend Aesthetics Guidelines + +Focus on: +- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font. +- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes. +- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise. +- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density. +- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays. + +NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character. + +Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations. + +**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well. + +Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision. diff --git a/development-log.md b/development-log.md new file mode 100644 index 0000000..061e4ab --- /dev/null +++ b/development-log.md @@ -0,0 +1,58 @@ + + +# 开发记录 + +## 2026-01-28 +### 开发辅助能力增强 +- 安装 frontend-design skill 到 .agents/skills 目录,增强前端设计与开发辅助能力 +- 路径:.agents/skills/frontend-design + +## 2026-01-27 +### PDF 功能统一与优化 +- 统一 PDF.js worker 引用为 public 根路径,减少各工具重复打包与加载 +- 补齐并统一 PDF 文件校验逻辑(类型与大小),提高一致性与用户提示准确性 +- 按规范更新工具页版权信息块 +- 为关键函数补充中文函数级注释,提升代码可维护性 +- 通过 vue-tsc 与构建校验验证改动有效性 + +- 更新文件与关键行号: + - src/utils/pdf.ts(L1-L6, L21-L31) + - src/components/Tools/PdfEncrypt/index.vue(L1-L8, L137-L151, L256-L274, L285-L326) + - src/components/Tools/PdfMerge/index.vue(L1-L8, L228-L233) + - src/components/Tools/PdfRotate/index.vue(L1-L8, L206-L211) + - src/components/Tools/PdfSplit/index.vue(L1-L8, L178-L191) + - src/components/Tools/PdfWatermark/index.vue(L1-L8, L178-L191) + - src/components/Tools/PdfPageNumber/index.vue(L1-L8, L185-L198, L310-L330, L391-L459) + - src/components/Tools/PdfExtractText/index.vue(L1-L8, L184-L196, L306-L326, L337-L421) + - src/components/Tools/PdfSign/index.vue(L1-L8, L139-L152, L250-L269, L410-L477) + - src/components/Tools/PdfToImages/index.vue(L1-L8, L254-L266, L413-L417, L298-L320) +- 为视频转 GIF 增加超过 5 次需公众号密码验证的限制,复用 DeepSeek 验证逻辑与提示文案 +- 抽离“关注公众号获取密码”弹窗为可复用组件,支持自定义文案与按钮文案 +- 修复工具详情获取方法缺失,新增根据路由或ID匹配工具信息逻辑 +- 更新文件:src/store/modules/tools.ts +- 修复外包报价与小红书等 AI 工具的类型与逻辑报错 +- 更新文件:src/components/Tools/AI/AIOutsourceQuote.vue、src/components/Tools/AI/AIRanking.vue、src/components/Tools/AI/AIResume.vue、src/components/Tools/AI/OCRRecognition.vue、src/components/Tools/AI/XiaoHongShu.vue、src/components/Tools/AI/XunfeiSpark.vue +- 修复 Header 与字体页面的类型报错 +- 更新文件:src/components/Layout/Header/Header.vue、src/components/Tools/Design/Font.vue +- 视频转 GIF 标题增加“免费”,修复转换流程与 workerScript 引用 +- 更新文件:src/components/Tools/Video/VideoToGif/VideoToGif.vue(L12-L209, L320-L322) +- 补充项目开发规范条目 +- 更新文件:.trae/rules/guifan.md(L2-L6) +- 根据项目现状完善规范,补充工具页版权块、路由/工具配置同步、worker 路径与类型定义要求 +- 更新文件:.trae/rules/guifan.md(L1-L13) +- 拆分工具配置逻辑为常量数据,并统一工具类型定义引用 +- 合并重复路由入口,统一 PDF 与 AI 快讯标题规则,移除重复的 AI 分析报告入口 +- 更新文件:src/components/Tools/tools.ts(L1-L3827) +- 更新文件:src/types/tools.ts(L1-L50) +- 更新文件:src/store/modules/tools.ts(L1-L223) +- 更新文件:src/components/Home/Home.vue(L18-L36) +- 更新文件:src/components/Tools/RandomTools/RandomTools.vue(L110-L159) +- 更新文件:src/components/Layout/Left/Left.vue(L17-L535) +- 更新文件:src/router/router.ts(L152-L999, L1262-L1271, L2658-L2666) diff --git a/docs/development-log.md b/docs/development-log.md new file mode 100644 index 0000000..e69de29 diff --git a/package-lock.json b/package-lock.json index 4d2b41f..b78644f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,10 +19,12 @@ "@codemirror/view": "^6.22.1", "@devui-design/icons": "^1.4.0", "@element-plus/icons-vue": "^2.3.1", + "@heroicons/vue": "^2.2.0", "@imgly/background-removal": "^1.7.0", "@kangc/v-md-editor": "^2.3.18", "@toast-ui/editor": "^3.2.2", "@types/diff": "^7.0.2", + "@types/file-saver": "^2.0.7", "@types/tinycolor2": "^1.4.6", "@types/uuid": "^10.0.0", "@vue/runtime-core": "^3.5.13", @@ -47,8 +49,10 @@ "esm-potrace-wasm": "^0.4.1", "fabric": "^6.6.0", "figlet": "^1.7.0", + "file-saver": "^2.0.5", "gifuct-js": "^2.1.2", "highlight.js": "^11.11.1", + "html-docx-js-typescript": "^0.1.5", "html2canvas": "^1.4.1", "html2pdf.js": "^0.10.2", "image-conversion": "^2.1.1", @@ -93,8 +97,6 @@ "devDependencies": { "@types/crypto-js": "^4.2.2", "@types/qrcode": "^1.5.6", - "@types/vue": "^1.0.31", - "@types/vue-router": "^2.0.0", "@vitejs/plugin-vue": "^4.5.1", "@vue/test-utils": "^2.4.6", "autoprefixer": "^10.4.16", @@ -105,13 +107,14 @@ "path": "^0.12.7", "pinia": "^2.1.7", "tailwindcss": "^3.3.5", - "typescript": "^4.9.5", + "typescript": "^5.6.3", + "unenv": "^1.10.0", "vite": "^4.5.1", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.23.0", + "vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-svg-icons": "^2.0.1", "vitest": "^4.0.14", - "vue-tsc": "^1.8.24" + "vue-tsc": "^2.1.10" } }, "node_modules/@acemir/cssom": { @@ -1043,6 +1046,15 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", "license": "MIT" }, + "node_modules/@heroicons/vue": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@heroicons/vue/-/vue-2.2.0.tgz", + "integrity": "sha512-G3dbSxoeEKqbi/DFalhRxJU4mTXJn7GwZ7ae8NuEQzd1bqdd0jAbdaBZlHPcvPD2xI1iGzNVB4k20Un2AguYPw==", + "license": "MIT", + "peerDependencies": { + "vue": ">= 3" + } + }, "node_modules/@iktakahiro/markdown-it-katex": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/@iktakahiro/markdown-it-katex/-/markdown-it-katex-4.0.1.tgz", @@ -2594,6 +2606,12 @@ "integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==", "license": "MIT" }, + "node_modules/@types/file-saver": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", + "license": "MIT" + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmmirror.com/@types/glob/-/glob-7.2.0.tgz", @@ -2717,24 +2735,6 @@ "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "license": "MIT" }, - "node_modules/@types/vue": { - "version": "1.0.31", - "resolved": "https://registry.npmmirror.com/@types/vue/-/vue-1.0.31.tgz", - "integrity": "sha512-unhlPKHFYEc+NA7nBz8yYSg7MOhWFJF2M/tzjb0rgVuK4pQzUBGmBp3IhfuhYDo3wr3dgA5sm9GUHmUJz2Hb9w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/vue-router": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@types/vue-router/-/vue-router-2.0.0.tgz", - "integrity": "sha512-E454lQ6tp9ftVWdZ8VGZpRcIV4YeqVAcx/uifl3P1GGwscYsxOFdYfgIuKasKO0Fm6Np2JM/L378D3bcRQE9hg==", - "deprecated": "This is a stub types definition for vue-router (https://github.com/vuejs/vue-router). ecmarkup provides its own type definitions, so you don\\'t need @types/ecmarkup installed!", - "dev": true, - "license": "MIT", - "dependencies": { - "vue-router": "*" - } - }, "node_modules/@types/web-bluetooth": { "version": "0.0.20", "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", @@ -3010,34 +3010,32 @@ } }, "node_modules/@volar/language-core": { - "version": "1.11.1", - "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-1.11.1.tgz", - "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "1.11.1" + "@volar/source-map": "2.4.15" } }, "node_modules/@volar/source-map": { - "version": "1.11.1", - "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-1.11.1.tgz", - "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", "dev": true, - "license": "MIT", - "dependencies": { - "muggle-string": "^0.3.1" - } + "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "1.11.1", - "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-1.11.1.tgz", - "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, "node_modules/@vue/compiler-core": { @@ -3090,6 +3088,17 @@ "@vue/shared": "3.5.13" } }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, "node_modules/@vue/devtools-api": { "version": "6.6.4", "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", @@ -3097,21 +3106,20 @@ "license": "MIT" }, "node_modules/@vue/language-core": { - "version": "1.8.27", - "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-1.8.27.tgz", - "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", - "computeds": "^0.0.1", + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" @@ -3123,9 +3131,9 @@ } }, "node_modules/@vue/language-core/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3826,6 +3834,13 @@ "ajv": "^8.8.2" } }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz", @@ -4501,6 +4516,12 @@ "dev": true, "license": "MIT" }, + "node_modules/browser-or-node": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/browser-or-node/-/browser-or-node-1.3.0.tgz", + "integrity": "sha512-0F2z/VSnLbmEeBcUrSuDH5l0HxTXdQQzLjkmBR4cYfvg1zJrKSlmIZFqyFR8oX0NrwPhy3c3HQ6i3OxMbew4Tg==", + "license": "MIT" + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -5352,13 +5373,6 @@ "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", "license": "MIT" }, - "node_modules/computeds": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/computeds/-/computeds-0.0.1.tgz", - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", @@ -6859,6 +6873,13 @@ "node": ">=0.10.0" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, "node_modules/degenerator": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/degenerator/-/degenerator-5.0.1.tgz", @@ -8509,6 +8530,12 @@ "node": ">=4" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz", @@ -9671,6 +9698,23 @@ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "license": "MIT" }, + "node_modules/html-docx-js-typescript": { + "version": "0.1.5", + "resolved": "https://registry.npmmirror.com/html-docx-js-typescript/-/html-docx-js-typescript-0.1.5.tgz", + "integrity": "sha512-GNojWFDYbpHSIgKml6/0oAom8mtHrHRTWKMyLRdeJQHO/CyeM6H39DYgzYvPp4OhBp2Ti8dxMKFq0/FkpYD4bg==", + "license": "MIT", + "dependencies": { + "browser-or-node": "^1.2.1", + "jszip": "^3.4.0", + "tslib": "^1.13.0" + } + }, + "node_modules/html-docx-js-typescript/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -12580,9 +12624,9 @@ "license": "MIT" }, "node_modules/muggle-string": { - "version": "0.3.1", - "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.3.1.tgz", - "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "dev": true, "license": "MIT" }, @@ -12790,6 +12834,13 @@ } } }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmmirror.com/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "dev": true, + "license": "MIT" + }, "node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", @@ -18239,9 +18290,9 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -18249,7 +18300,7 @@ "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { @@ -18302,6 +18353,50 @@ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "license": "MIT" }, + "node_modules/unenv": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/unenv/-/unenv-1.10.0.tgz", + "integrity": "sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3", + "defu": "^6.1.4", + "mime": "^3.0.0", + "node-fetch-native": "^1.6.4", + "pathe": "^1.1.2" + } + }, + "node_modules/unenv/node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/unenv/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/unenv/node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, "node_modules/unhead": { "version": "1.11.20", "resolved": "https://registry.npmmirror.com/unhead/-/unhead-1.11.20.tgz", @@ -18786,9 +18881,9 @@ } }, "node_modules/vite-plugin-node-polyfills": { - "version": "0.23.0", - "resolved": "https://registry.npmmirror.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.23.0.tgz", - "integrity": "sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w==", + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.24.0.tgz", + "integrity": "sha512-GA9QKLH+vIM8NPaGA+o2t8PDfFUl32J8rUp1zQfMKVJQiNkOX4unE51tR6ppl6iKw5yOrDAdSH7r/UIFLCVhLw==", "dev": true, "license": "MIT", "dependencies": { @@ -18799,7 +18894,7 @@ "url": "https://github.com/sponsors/davidmyersdev" }, "peerDependencies": { - "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "node_modules/vite-plugin-seo-prerender": { @@ -19702,6 +19797,13 @@ "dev": true, "license": "MIT" }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vue": { "version": "3.5.13", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz", @@ -20068,46 +20170,21 @@ "vue": "^3.2.0" } }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, "node_modules/vue-tsc": { - "version": "1.8.27", - "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-1.8.27.tgz", - "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", - "semver": "^7.5.4" + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" }, "bin": { "vue-tsc": "bin/vue-tsc.js" }, "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/vue-tsc/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "typescript": ">=5.0.0" } }, "node_modules/vue3-danmaku": { diff --git a/package.json b/package.json index d572d66..f60b646 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "scripts": { "dev": "vite", "build": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build", - "build:check": "vue-tsc && vite build", - "build:pro": "vue-tsc --noEmit && node --max_old_space_size=8192 node_modules/vite/bin/vite.js build --mode production", + "build:check": "NODE_OPTIONS=--max-old-space-size=8192 vue-tsc --noEmit && vite build", + "build:pro": "NODE_OPTIONS=--max-old-space-size=8192 vue-tsc --noEmit && node --max_old_space_size=8192 node_modules/vite/bin/vite.js build --mode production", "preview": "vite preview", "test:unit": "vitest" }, @@ -28,6 +28,7 @@ "@kangc/v-md-editor": "^2.3.18", "@toast-ui/editor": "^3.2.2", "@types/diff": "^7.0.2", + "@types/file-saver": "^2.0.7", "@types/tinycolor2": "^1.4.6", "@types/uuid": "^10.0.0", "@vue/runtime-core": "^3.5.13", @@ -52,8 +53,10 @@ "esm-potrace-wasm": "^0.4.1", "fabric": "^6.6.0", "figlet": "^1.7.0", + "file-saver": "^2.0.5", "gifuct-js": "^2.1.2", "highlight.js": "^11.11.1", + "html-docx-js-typescript": "^0.1.5", "html2canvas": "^1.4.1", "html2pdf.js": "^0.10.2", "image-conversion": "^2.1.1", @@ -98,8 +101,6 @@ "devDependencies": { "@types/crypto-js": "^4.2.2", "@types/qrcode": "^1.5.6", - "@types/vue": "^1.0.31", - "@types/vue-router": "^2.0.0", "@vitejs/plugin-vue": "^4.5.1", "@vue/test-utils": "^2.4.6", "autoprefixer": "^10.4.16", @@ -110,12 +111,13 @@ "path": "^0.12.7", "pinia": "^2.1.7", "tailwindcss": "^3.3.5", - "typescript": "^4.9.5", + "typescript": "^5.6.3", + "unenv": "^1.10.0", "vite": "^4.5.1", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.23.0", + "vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-svg-icons": "^2.0.1", "vitest": "^4.0.14", - "vue-tsc": "^1.8.24" + "vue-tsc": "^2.1.10" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abcf7a1..7a320c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,6 +56,9 @@ importers: '@types/diff': specifier: ^7.0.2 version: 7.0.2 + '@types/file-saver': + specifier: ^2.0.7 + version: 2.0.7 '@types/tinycolor2': specifier: ^1.4.6 version: 1.4.6 @@ -128,12 +131,18 @@ importers: figlet: specifier: ^1.7.0 version: 1.9.4 + file-saver: + specifier: ^2.0.5 + version: 2.0.5 gifuct-js: specifier: ^2.1.2 version: 2.1.2 highlight.js: specifier: ^11.11.1 version: 11.11.1 + html-docx-js-typescript: + specifier: ^0.1.5 + version: 0.1.5 html2canvas: specifier: ^1.4.1 version: 1.4.1 @@ -300,6 +309,9 @@ importers: typescript: specifier: ^4.9.5 version: 4.9.5 + unenv: + specifier: ^1.10.0 + version: 1.10.0 vite: specifier: ^4.5.1 version: 4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1) @@ -307,8 +319,8 @@ importers: specifier: ^3.2.0 version: 3.2.2(vite@4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1)) vite-plugin-node-polyfills: - specifier: ^0.23.0 - version: 0.23.1(rollup@4.53.5)(vite@4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1)) + specifier: ^0.24.0 + version: 0.24.0(rollup@4.53.5)(vite@4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1)) vite-plugin-svg-icons: specifier: ^2.0.1 version: 2.0.1(vite@4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1)) @@ -1180,6 +1192,9 @@ packages: '@types/event-emitter@0.3.5': resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==} + '@types/file-saver@2.0.7': + resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==} + '@types/glob@7.2.0': resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} @@ -1918,6 +1933,9 @@ packages: brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + browser-or-node@1.3.0: + resolution: {integrity: sha512-0F2z/VSnLbmEeBcUrSuDH5l0HxTXdQQzLjkmBR4cYfvg1zJrKSlmIZFqyFR8oX0NrwPhy3c3HQ6i3OxMbew4Tg==} + browser-process-hrtime@1.0.0: resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} @@ -2192,6 +2210,10 @@ packages: consola@2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + console-browserify@1.2.0: resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} @@ -2700,6 +2722,9 @@ packages: resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} engines: {node: '>=0.10.0'} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} @@ -3165,6 +3190,9 @@ packages: resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} engines: {node: '>=4'} + file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -3471,6 +3499,9 @@ packages: hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + html-docx-js-typescript@0.1.5: + resolution: {integrity: sha512-GNojWFDYbpHSIgKml6/0oAom8mtHrHRTWKMyLRdeJQHO/CyeM6H39DYgzYvPp4OhBp2Ti8dxMKFq0/FkpYD4bg==} + html-encoding-sniffer@1.0.2: resolution: {integrity: sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==} @@ -4299,6 +4330,11 @@ packages: engines: {node: '>=4'} hasBin: true + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + mimic-fn@1.2.0: resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} engines: {node: '>=4'} @@ -4443,6 +4479,9 @@ packages: node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + node-fetch@1.6.3: resolution: {integrity: sha512-BDxbhLHXFFFvilHjh9xihcDyPkXQ+kjblxnl82zAX41xUYSNvuRpFRznmldR9+OKu+p+ULZ7hNoyunlLB5ecUA==} @@ -4711,6 +4750,9 @@ packages: pathe@0.2.0: resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -5808,6 +5850,9 @@ packages: resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} engines: {node: '>=20.18.1'} + unenv@1.10.0: + resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==} + unhead@1.11.20: resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==} @@ -5918,9 +5963,8 @@ packages: peerDependencies: vite: '>=2.0.0' - vite-plugin-node-polyfills@0.23.1: - resolution: {integrity: sha512-hR2YlaMqVo2f/0w6V9YgaeKsIy8z5gEsMFHX8MQlh8ATEAbfI4EWjE6qnCvkZ9lyaXKoJD2rAwL/up8/Rzsjkg==} - deprecated: this version is broken + vite-plugin-node-polyfills@0.24.0: + resolution: {integrity: sha512-GA9QKLH+vIM8NPaGA+o2t8PDfFUl32J8rUp1zQfMKVJQiNkOX4unE51tR6ppl6iKw5yOrDAdSH7r/UIFLCVhLw==} peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -7083,6 +7127,8 @@ snapshots: '@types/event-emitter@0.3.5': {} + '@types/file-saver@2.0.7': {} + '@types/glob@7.2.0': dependencies: '@types/minimatch': 6.0.0 @@ -7965,6 +8011,8 @@ snapshots: brorand@1.1.0: {} + browser-or-node@1.3.0: {} + browser-process-hrtime@1.0.0: optional: true @@ -8295,6 +8343,8 @@ snapshots: consola@2.15.3: {} + consola@3.4.2: {} + console-browserify@1.2.0: {} console-control-strings@1.1.0: @@ -8923,6 +8973,8 @@ snapshots: is-descriptor: 1.0.3 isobject: 3.0.1 + defu@6.1.4: {} + degenerator@5.0.1: dependencies: ast-types: 0.13.4 @@ -9558,6 +9610,8 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 + file-saver@2.0.5: {} + filelist@1.0.4: dependencies: minimatch: 5.1.6 @@ -9907,6 +9961,12 @@ snapshots: hookable@5.5.3: {} + html-docx-js-typescript@0.1.5: + dependencies: + browser-or-node: 1.3.0 + jszip: 3.10.1 + tslib: 1.14.1 + html-encoding-sniffer@1.0.2: dependencies: whatwg-encoding: 1.0.5 @@ -10703,7 +10763,7 @@ snapshots: md5.js@1.3.5: dependencies: - hash-base: 3.0.5 + hash-base: 3.1.2 inherits: 2.0.4 safe-buffer: 5.2.1 @@ -10977,6 +11037,8 @@ snapshots: mime@1.6.0: optional: true + mime@3.0.0: {} + mimic-fn@1.2.0: {} mimic-response@2.1.0: @@ -11112,6 +11174,8 @@ snapshots: node-addon-api@7.1.1: optional: true + node-fetch-native@1.6.7: {} + node-fetch@1.6.3: dependencies: encoding: 0.1.13 @@ -11428,6 +11492,8 @@ snapshots: pathe@0.2.0: {} + pathe@1.1.2: {} + pathe@2.0.3: {} pbkdf2@3.1.5: @@ -12750,6 +12816,14 @@ snapshots: undici@7.16.0: {} + unenv@1.10.0: + dependencies: + consola: 3.4.2 + defu: 6.1.4 + mime: 3.0.0 + node-fetch-native: 1.6.7 + pathe: 1.1.2 + unhead@1.11.20: dependencies: '@unhead/dom': 1.11.20 @@ -12882,7 +12956,7 @@ snapshots: pathe: 0.2.0 vite: 4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1) - vite-plugin-node-polyfills@0.23.1(rollup@4.53.5)(vite@4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1)): + vite-plugin-node-polyfills@0.24.0(rollup@4.53.5)(vite@4.5.14(@types/node@25.0.2)(less@4.5.1)(sass@1.97.0)(terser@5.44.1)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.53.5) node-stdlib-browser: 1.3.1 diff --git a/tsconfig.json b/tsconfig.json index 3d429cc..125c604 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,14 +10,14 @@ ], "skipLibCheck": true, /* Bundler mode */ - "moduleResolution": "node", + "moduleResolution": "bundler", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "preserve", /* Linting */ - "strict": true, + "strict": false, "noUnusedLocals": false, "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, @@ -28,10 +28,8 @@ "src/*" ] }, - /* Vue */ "types": [ - "vue", - "vue-router" + "vite/client" ], "allowSyntheticDefaultImports": true, "esModuleInterop": true, @@ -45,7 +43,6 @@ "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", - "ssr.config.ts" ], "references": [ { diff --git a/tsconfig.node.json b/tsconfig.node.json index 5e96b40..2fcba5c 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -9,10 +9,6 @@ }, "include": [ "vite.config.ts", - "ssr.config.ts", - "src/**/*.ts", - "src/**/*.d.ts", - "src/**/*.tsx", - "src/**/*.vue" + "ssr.config.ts" ] } From d9c8dd668164719b3bb1829f9792e906872a98fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Tue, 17 Mar 2026 14:27:30 +0800 Subject: [PATCH 19/45] =?UTF-8?q?refactor:=20=E8=B7=AF=E7=94=B1=E4=B8=8E?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E9=85=8D=E7=BD=AE=E5=8E=BB=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Tools/tools.ts | 106 +++------------------------------- src/router/router.ts | 64 +------------------- 2 files changed, 9 insertions(+), 161 deletions(-) diff --git a/src/components/Tools/tools.ts b/src/components/Tools/tools.ts index cd6b86b..4e7ea9d 100644 --- a/src/components/Tools/tools.ts +++ b/src/components/Tools/tools.ts @@ -186,17 +186,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 913, - title: '半年工作总结', - logo: { type: 'svg', name: 'aiArticle' }, - desc: '对半年度工作进行系统梳理和总结,展望下半年工作重点', - url: '/tools/ai/work-summary?type=mid_year', - cate: 'AI办公工具', - releaseDate: '2025/12/16 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 914, title: '部门计划', @@ -395,17 +384,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 933, - title: '会议记录润色', - logo: { type: 'svg', name: 'aiArticle' }, - desc: '智能整理和润色会议记录,生成结构清晰、重点突出的会议纪要', - url: '/tools/ai/office/meeting-minutes', - cate: 'AI办公工具', - releaseDate: '2025/12/16 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 934, title: '竟聘演讲稿', @@ -428,17 +406,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 936, - title: '离职申请', - logo: { type: 'svg', name: 'aiArticle' }, - desc: '智能生成得体、专业的辞职报告,保持良好职业形象', - url: '/tools/ai/office/resignation-letter', - cate: 'AI办公工具', - releaseDate: '2025/12/16 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 937, title: '问卷设计', @@ -450,17 +417,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 938, - title: '通稿润色改写', - logo: { type: 'svg', name: 'aiArticle' }, - desc: '智能改写文本,降低查重率,优化语言表达,提升文章质量', - url: '/tools/ai/article-polishing', - cate: 'AI办公工具', - releaseDate: '2025/12/16 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 939, title: '标书撰写', @@ -1135,17 +1091,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 702, - title: 'AI工作总结', - logo: { type: 'svg', name: 'aiArticle' }, // Reusing icon for now - desc: '智能生成专业的工作总结,包含工作成果、问题分析和未来规划', - url: '/tools/ai/work-summary', - cate: 'AI写作工具', - releaseDate: '2025/12/15 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 703, title: 'AI实习总结', @@ -1245,17 +1190,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 713, - title: '述职报告', - logo: { type: 'svg', name: 'aiArticle' }, - desc: '智能生成个人述职报告,突出工作业绩和职业亮点', - url: '/tools/ai/debriefing-report', - cate: 'AI写作工具', - releaseDate: '2025/12/15 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 714, title: '作文一键写作', @@ -1344,17 +1278,6 @@ const toolsCategories: ToolCategory[] = [ tags: ['免费', '新品'], isNew: true }, - { - id: 722, - title: '项目策划方案', - logo: { type: 'svg', name: 'aiArticle' }, - desc: '智能生成专业的项目策划方案,包含背景、目标、实施计划和预算预估', - url: '/tools/ai/project-proposal', - cate: 'AI写作工具', - releaseDate: '2025/12/16 00:00:00', - tags: ['免费', '新品'], - isNew: true - }, { id: 723, title: '讲话稿', @@ -3165,16 +3088,6 @@ const toolsCategories: ToolCategory[] = [ cateId: 2, cate: '开发运维' }, - { - id: 2114, - title: 'Cron表达式生成器', - logo: { type: 'svg', name: 'cron' }, - desc: '可视化生成和解析 Cron 表达式', - url: '/tools/dev/cron', - cateId: 2, - cate: '开发运维', - isNew: true - }, { id: 2115, title: '变量命名转换', @@ -3206,17 +3119,6 @@ const toolsCategories: ToolCategory[] = [ isNew: true, tags: ['免费', '新品'] }, - { - id: 2119, - title: 'CSS 渐变生成器', - logo: { type: 'svg', name: 'gradient' }, - desc: '在线生成精美的 CSS 线性渐变和径向渐变背景代码,支持多种颜色和方向设置', - url: '/tools/design/gradient', - cateId: 2, - cate: '开发运维', - isNew: true, - tags: ['免费', '新品'] - }, { id: 2120, title: 'Meta 标签生成器', @@ -3772,6 +3674,8 @@ export function getToolsCate(): ToolCategory[] { export function toolsList() { let list = [] as Tool[] let toolsCate = getToolsCate() + // 使用 URL 去重,避免同一路径工具在搜索和推荐中重复出现 + const seenToolUrls = new Set() // 递归处理嵌套的工具列表 const processTools = (tools: any[]) => { @@ -3779,7 +3683,11 @@ export function toolsList() { if (Array.isArray(tool.list)) { processTools(tool.list) } else { - list.push(tool) + const toolUrl = tool.url || `id:${tool.id}` + if (!seenToolUrls.has(toolUrl)) { + seenToolUrls.add(toolUrl) + list.push(tool) + } } } } diff --git a/src/router/router.ts b/src/router/router.ts index 6b86242..b328e63 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -1086,24 +1086,14 @@ export const constantRoute: RouteRecordRaw[] = [ }, { path: '/tools/video/audio', - component: () => import('@/components/Tools/Video/VideoToAudio/VideoToAudio.vue'), - name: 'videoToAudio', + redirect: '/tools/video/to-audio', + name: 'videoToAudioLegacy', meta: { title: "视频提取音频", keywords: '视频提取音频,视频转音频,视频转MP3,提取背景音乐', description: '在线从视频中提取音频,支持导出为 WAV 格式。' } }, - { - path: '/tools/design/font-copyright', - component: () => import('@/components/Tools/Design/FontCopyright.vue'), - name: 'fontCopyright', - meta: { - title: "字体版权查询", - keywords: '字体版权,商用字体,免费字体,字体查询', - description: '查询字体版权信息,确认是否可以免费商用,避免版权纠纷。' - } - }, { path: '/tools/life/countdown', component: () => import('@/components/Tools/Life/CountdownDay.vue'), @@ -1164,26 +1154,6 @@ export const constantRoute: RouteRecordRaw[] = [ description: '在线视频倍速处理工具,支持0.5x到4.0x速度调整,支持导出处理后的视频,本地处理更安全。' } }, - { - path: '/tools/video/rotate', - component: () => import('@/components/Tools/Video/VideoFlip/VideoFlip.vue'), - name: 'videoFlip', - meta: { - title: "视频旋转/翻转", - keywords: '视频旋转,视频翻转,视频角度调整,在线视频旋转', - description: '在线旋转视频角度(90°/180°/270°)或进行水平/垂直翻转,本地处理保护隐私。' - } - }, - { - path: '/tools/audio/converter', - component: () => import('@/components/Tools/Audio/AudioConverter/AudioConverter.vue'), - name: 'audioConverter', - meta: { - title: "音频格式转换", - keywords: '音频格式转换,MP3转换,WAV转换,音频转码,在线音频转换', - description: '在线音频格式转换工具,支持 WAV、WebM 等格式互转。' - } - }, { path: '/tools/audio/trimmer', component: () => import('@/components/Tools/Audio/AudioTrimmer/AudioTrimmer.vue'), @@ -1214,16 +1184,6 @@ export const constantRoute: RouteRecordRaw[] = [ description: '将 URL 解析为协议、主机、路径、查询参数等组成部分,支持一键复制。' } }, - { - path: '/tools/dev/cron', - component: () => import('@/components/Tools/Dev/Cron/Cron.vue'), - name: 'cron', - meta: { - title: "Cron 表达式生成器", - keywords: 'Cron表达式,Cron生成器,定时任务,Quartz,Crontab', - description: '可视化生成 Cron 表达式,支持 Quartz 和 Linux Crontab 格式,提供常用示例。' - } - }, { path: '/tools/doc/spec', component: () => import('@/components/Tools/Doc/DocSpec/DocSpec.vue'), @@ -1883,26 +1843,6 @@ export const constantRoute: RouteRecordRaw[] = [ description: '测试你的情商水平,了解你的情绪管理和人际交往能力', } }, - { - path: '/tools/psychology/eq-test', - component: () => import('@/components/Tools/Psychology/EQTest.vue'), - name: 'eqTest', - meta: { - title: "国际标准情商(EQ)测试", - keywords: 'EQ测试,情商测试,情绪管理,社交能力', - description: '评估你的情绪感知、控制和社交能力,了解你的情商水平', - } - }, - { - path: '/tools/psychology/left-right-brain', - component: () => import('@/components/Tools/Psychology/LeftRightBrain.vue'), - name: 'leftRightBrain', - meta: { - title: "左右脑优势测试", - keywords: '左右脑测试,大脑优势,思维偏好,逻辑与直觉', - description: '了解你是理性逻辑的左脑型,还是感性创意的右脑型', - } - }, { path: '/tools/morse', component: () => import('@/components/Tools/Morse/Morse.vue'), From 145b0d6f0f2609b10ef1e8b2267a264242aaa05a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Tue, 17 Mar 2026 14:29:12 +0800 Subject: [PATCH 20/45] =?UTF-8?q?style:=20=E5=AF=B9=E9=BD=90=E5=85=A8?= =?UTF-8?q?=E7=AB=99=E5=B8=83=E5=B1=80=E4=BC=98=E5=8C=96=20mobile-ui-spec?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Tools/Design/MobileUISpec.vue | 358 ++++++++++++++++++- 1 file changed, 340 insertions(+), 18 deletions(-) diff --git a/src/components/Tools/Design/MobileUISpec.vue b/src/components/Tools/Design/MobileUISpec.vue index 7ba5102..2f357b4 100644 --- a/src/components/Tools/Design/MobileUISpec.vue +++ b/src/components/Tools/Design/MobileUISpec.vue @@ -12,19 +12,25 @@
        -
        +

        - 移动端UI设计规范 + 移动端 UI 设计规范

        -

        提供 iOS 和 Android 平台的详细UI设计规范,帮助设计师快速掌握不同平台的设计标准

        +

        提供 iOS 与 Android 平台尺寸、组件与交互规范,帮助设计与开发快速对齐。

        + +
        + {{ platformSummary.platform }} + {{ platformSummary.deviceCount }} + {{ platformSummary.unit }} +
        -
        +
        +

        {{ platformSummary.tip }}

        +
        + +
        +
        +

        结构导览

        +

        按「尺寸规范 → 设计原则 → 平台比较」的顺序浏览,能更快完成平台选型和交付评审。

        +
        + +
        + +
        + +
        +
        + {{ metric.label }} + {{ metric.value }} +
        +
        -

        iOS 设计准则

        +

        iOS 尺寸与组件规范

        @@ -590,7 +628,7 @@
        -

        iOS 设计准则

        +

        iOS 设计原则与交互模式

        @@ -899,7 +937,7 @@
        < 返回
        详情
        -
        +
        @@ -1078,7 +1116,7 @@
        -

        尺寸规范

        +

        Android 尺寸与组件规范

        @@ -1164,7 +1202,7 @@
        -
        +
        @@ -1177,7 +1215,7 @@
        -
        +
        @@ -1268,7 +1306,7 @@
        -

        - AI文献推荐 + 免费 AI文献推荐

        智能推荐相关领域的高质量文献,助力学术研究和论文写作

        diff --git a/src/components/Tools/AI/Writing/LiteratureReview.vue b/src/components/Tools/AI/Writing/LiteratureReview.vue index 1932dbd..317eb39 100644 --- a/src/components/Tools/AI/Writing/LiteratureReview.vue +++ b/src/components/Tools/AI/Writing/LiteratureReview.vue @@ -19,7 +19,7 @@

        - 文献综述 + 免费文献综述

        智能生成专业文献综述,支持多种学术领域

        diff --git a/src/components/Tools/AI/Writing/NovelPlot.vue b/src/components/Tools/AI/Writing/NovelPlot.vue index df3c6d2..f81097c 100644 --- a/src/components/Tools/AI/Writing/NovelPlot.vue +++ b/src/components/Tools/AI/Writing/NovelPlot.vue @@ -19,7 +19,7 @@

        - 小说剧情创作 + 免费小说剧情创作

        智能生成小说剧情大纲、角色设定和故事梗概

        diff --git a/src/components/Tools/AI/Writing/OpeningReport.vue b/src/components/Tools/AI/Writing/OpeningReport.vue index cb4e744..2e5be51 100644 --- a/src/components/Tools/AI/Writing/OpeningReport.vue +++ b/src/components/Tools/AI/Writing/OpeningReport.vue @@ -19,7 +19,7 @@

        - AI开题报告 + 免费 AI开题报告

        智能生成标准规范的开题报告,包含选题意义、研究现状、内容方法和进度安排

        diff --git a/src/components/Tools/AI/Writing/PracticeReport.vue b/src/components/Tools/AI/Writing/PracticeReport.vue index 4a95e0b..58c54c4 100644 --- a/src/components/Tools/AI/Writing/PracticeReport.vue +++ b/src/components/Tools/AI/Writing/PracticeReport.vue @@ -19,7 +19,7 @@

        - AI社会实践报告 + 免费 AI社会实践报告

        智能生成社会实践报告,记录实践过程,总结实践经验

        diff --git a/src/components/Tools/AI/Writing/ProjectProposal.vue b/src/components/Tools/AI/Writing/ProjectProposal.vue index 2c2f9ec..3491b5b 100644 --- a/src/components/Tools/AI/Writing/ProjectProposal.vue +++ b/src/components/Tools/AI/Writing/ProjectProposal.vue @@ -19,7 +19,7 @@

        - AI项目策划方案 + 免费 AI项目策划方案

        智能生成专业的项目策划方案,包含背景、目标、实施计划和预算预估

        @@ -46,23 +46,28 @@ class="custom-input" />
        -
        - - -
        - -
        - - -
        - -
        - - -
        +
        + 高级选项(可选) +
        +
        + + +
        + +
        + + +
        + +
        + + +
        +
        +
        @@ -161,8 +166,16 @@
        - + +
        @@ -176,7 +189,7 @@ From 03564a96ede4b6af1279a471579b0482482fbc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Wed, 18 Mar 2026 20:13:40 +0800 Subject: [PATCH 35/45] =?UTF-8?q?perf(ai-tools):=20=E4=BC=98=E5=8C=96=20AI?= =?UTF-8?q?=20=E5=9B=9B=E4=B8=AA=E5=88=86=E7=BB=84=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E5=8A=A0=E8=BD=BD=E9=93=BE=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tools/AI/Analysis/ActivityPlan.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/AnalysisReport.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/BostonAnalysis.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/BusinessPlan.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/FeasibilityStudy.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/IndustryConsultant.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/IndustryReport.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/InnovationIdea.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/Marketing4p.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/PestAnalysis.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/ProjectApplication.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/ResearchReport.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/SituationReport.vue | 111 +++++++++++++++- .../Tools/AI/Analysis/SurveyReport.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/SwotAnalysis.vue | 106 ++++++++++++++- .../Tools/AI/Analysis/TransportPlan.vue | 111 +++++++++++++++- .../Tools/AI/Office/ApplicationReport.vue | 118 ++++++++++++++++- .../Tools/AI/Office/CompetitorSpeech.vue | 120 ++++++++++++++++- .../Tools/AI/Office/ContractTemplate.vue | 124 +++++++++++++++--- .../Tools/AI/Office/CoverLetter.vue | 118 ++++++++++++++++- .../Tools/AI/Office/CustomSummary.vue | 118 ++++++++++++++++- .../Tools/AI/Office/DesignConcept.vue | 120 ++++++++++++++++- .../Tools/AI/Office/HolidayNotice.vue | 118 ++++++++++++++++- .../Tools/AI/Office/InterviewOutline.vue | 118 ++++++++++++++++- .../Tools/AI/Office/JobDescription.vue | 118 ++++++++++++++++- .../Tools/AI/Office/LawsuitDocument.vue | 118 ++++++++++++++++- .../Tools/AI/Office/MeetingMinutes.vue | 120 ++++++++++++++++- .../Tools/AI/Office/NoticeGenerator.vue | 106 ++++++++++++++- .../Tools/AI/Office/NoticeWriting.vue | 118 ++++++++++++++++- .../Tools/AI/Office/OKRGenerator.vue | 115 ++++++++++++++-- .../Tools/AI/Office/QuestionnaireDesign.vue | 120 ++++++++++++++++- .../Tools/AI/Office/ResignationLetter.vue | 118 ++++++++++++++++- .../Tools/AI/Office/ResumeBuilder.vue | 106 ++++++++++++++- .../Tools/AI/Office/ResumeCreation.vue | 118 ++++++++++++++++- .../Tools/AI/Office/TenderWriting.vue | 118 ++++++++++++++++- .../Tools/AI/Office/TrainingScheme.vue | 118 ++++++++++++++++- src/components/Tools/AI/Office/WorkPlan.vue | 118 ++++++++++++++++- .../Tools/AI/Office/WorkReflections.vue | 118 ++++++++++++++++- src/components/Tools/AI/Office/WorkReport.vue | 118 ++++++++++++++++- .../Tools/AI/Student/ActivityPlan.vue | 107 ++++++++++++++- .../Tools/AI/Student/AnalysisReport.vue | 107 ++++++++++++++- .../Tools/AI/Student/InternshipComments.vue | 107 ++++++++++++++- .../Tools/AI/Student/InternshipExperience.vue | 107 ++++++++++++++- .../Tools/AI/Student/InternshipReport.vue | 107 ++++++++++++++- .../Tools/AI/Student/InternshipSummary.vue | 107 ++++++++++++++- .../Tools/AI/Student/InternshipWeekly.vue | 107 ++++++++++++++- .../Tools/AI/Student/InterviewGuide.vue | 107 ++++++++++++++- .../Tools/AI/Student/PracticeReport.vue | 107 ++++++++++++++- .../Tools/AI/Student/ResearchReport.vue | 107 ++++++++++++++- .../Tools/AI/Student/ResumeCreation.vue | 107 ++++++++++++++- .../Tools/AI/Student/SocialPractice.vue | 107 ++++++++++++++- .../Tools/AI/Writing/AnalysisReport.vue | 107 ++++++++++++++- .../Tools/AI/Writing/ArticleOutline.vue | 106 ++++++++++++++- .../Tools/AI/Writing/ArticlePolishing.vue | 106 ++++++++++++++- .../Tools/AI/Writing/ArticleSummary.vue | 106 ++++++++++++++- .../Tools/AI/Writing/EssayContest.vue | 108 ++++++++++++++- .../Tools/AI/Writing/EssayWriting.vue | 117 ++++++++++++++++- .../Tools/AI/Writing/GraduationThesis.vue | 106 ++++++++++++++- .../Tools/AI/Writing/InternSummary.vue | 107 ++++++++++++++- .../Tools/AI/Writing/LiteratureRecommend.vue | 106 ++++++++++++++- .../Tools/AI/Writing/LiteratureReview.vue | 117 ++++++++++++++++- src/components/Tools/AI/Writing/NovelPlot.vue | 117 ++++++++++++++++- .../Tools/AI/Writing/OpeningReport.vue | 106 ++++++++++++++- .../Tools/AI/Writing/PracticeReport.vue | 107 ++++++++++++++- .../Tools/AI/Writing/SelfReflection.vue | 106 ++++++++++++++- .../Tools/AI/Writing/ShortVideoTitle.vue | 106 ++++++++++++++- .../Tools/AI/Writing/SpeechDraft.vue | 115 +++++++++++++++- .../Tools/AI/Writing/SpokespersonSpeech.vue | 108 ++++++++++++++- .../Tools/AI/Writing/TrainingExperience.vue | 108 ++++++++++++++- .../Tools/AI/Writing/WorkReportPPT.vue | 108 ++++++++++++++- 70 files changed, 7392 insertions(+), 396 deletions(-) diff --git a/src/components/Tools/AI/Analysis/ActivityPlan.vue b/src/components/Tools/AI/Analysis/ActivityPlan.vue index 532dc8d..b41108c 100644 --- a/src/components/Tools/AI/Analysis/ActivityPlan.vue +++ b/src/components/Tools/AI/Analysis/ActivityPlan.vue @@ -150,8 +150,16 @@
        - + +
        @@ -171,7 +179,7 @@ diff --git a/src/utils/toolRuntimeLoaders.ts b/src/utils/toolRuntimeLoaders.ts index 473f704..42ea049 100644 --- a/src/utils/toolRuntimeLoaders.ts +++ b/src/utils/toolRuntimeLoaders.ts @@ -27,6 +27,12 @@ type HighlightRuntime = { hljs: typeof import('highlight.js')['default'] } +type GifRuntime = { + GIF: typeof import('gif.js') + parseGIF: typeof import('gifuct-js').parseGIF + decompressFrames: typeof import('gifuct-js').decompressFrames +} + let htmlPrettierPromise: Promise | null = null let cssPrettierPromise: Promise | null = null let jsPrettierPromise: Promise | null = null @@ -38,6 +44,7 @@ let jsPdfPromise: Promise<{ jsPDF: typeof import('jspdf').jsPDF }> | null = null let markedPromise: Promise<{ marked: typeof import('marked').marked }> | null = null let xlsxPromise: Promise<{ XLSX: typeof import('xlsx') }> | null = null let highlightCorePromise: Promise | null = null +let gifRuntimePromise: Promise | null = null const highlightStylePromiseMap = new Map>() const highlightStyleLoaders = { @@ -236,3 +243,26 @@ export const ensureHighlightRuntime = async ( await highlightStylePromiseMap.get(normalizedTheme) return highlightCorePromise } + +/** + * 按需加载 GIF 压缩运行时 + * 首次压缩时动态引入 gif.js 与 gifuct-js,后续复用缓存 Promise + */ +export const ensureGifRuntime = async (): Promise => { + if (!gifRuntimePromise) { + gifRuntimePromise = (async () => { + const [gifModule, gifuctModule] = await Promise.all([ + import('gif.js'), + import('gifuct-js') + ]) + + return { + GIF: ((gifModule as any).default ?? gifModule) as typeof import('gif.js'), + parseGIF: gifuctModule.parseGIF, + decompressFrames: gifuctModule.decompressFrames + } + })() + } + + return gifRuntimePromise +} From 949920b4cdb47528df31b8c060a83e13c70c3141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=B0=E5=AD=97=E6=B8=B8=E6=B0=91Tomda?= <9923457+tomdac@user.noreply.gitee.com> Date: Wed, 18 Mar 2026 23:44:40 +0800 Subject: [PATCH 38/45] =?UTF-8?q?feat(search):=20=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=A3=80=E7=B4=A2=E5=85=9C=E5=BA=95=E4=B8=8E?= =?UTF-8?q?=E6=B5=81=E5=BC=8F=E8=A7=A3=E6=9E=90=E7=A8=B3=E5=AE=9A=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Search/Search.vue | 28 +-- src/services/ai.ts | 412 ++++++++++++++++++++----------- src/utils/toolSearch.ts | 150 +++++++++++ 3 files changed, 425 insertions(+), 165 deletions(-) create mode 100644 src/utils/toolSearch.ts diff --git a/src/components/Search/Search.vue b/src/components/Search/Search.vue index d67ba97..e03ad8a 100644 --- a/src/components/Search/Search.vue +++ b/src/components/Search/Search.vue @@ -25,7 +25,7 @@
        -
        +