From 47ef1a581f5197e417a9dc2bceb3f27976088350 Mon Sep 17 00:00:00 2001 From: dreamer6680 <1468683855@qq.com> Date: Fri, 25 Jul 2025 16:43:37 +0800 Subject: [PATCH] feat:get lastmodified time by git log (#5314) * feat:get lastmodified time by git log * fix:add sentence to run github.js for lastmodified time in pre-commit --- document/app/[lang]/docs/[[...slug]]/page.tsx | 26 ++- document/components/docs/not-found.tsx | 2 +- document/data/doc-last-modified.json | 187 ++++++++++++++++++ document/github.js | 182 +++++++++++++++++ document/package.json | 1 + package.json | 7 +- 6 files changed, 402 insertions(+), 3 deletions(-) create mode 100644 document/data/doc-last-modified.json create mode 100644 document/github.js diff --git a/document/app/[lang]/docs/[[...slug]]/page.tsx b/document/app/[lang]/docs/[[...slug]]/page.tsx index 38cb22e2e..8da1fbc26 100644 --- a/document/app/[lang]/docs/[[...slug]]/page.tsx +++ b/document/app/[lang]/docs/[[...slug]]/page.tsx @@ -4,6 +4,25 @@ import { notFound } from 'next/navigation'; import NotFound from '@/components/docs/not-found'; import { createRelativeLink } from 'fumadocs-ui/mdx'; import { getMDXComponents } from '@/mdx-components'; +import fs from 'fs'; +import path from 'path'; + +// 读取文档修改时间数据 +function getDocLastModifiedData(): Record { + try { + const dataPath = path.join(process.cwd(), 'data', 'doc-last-modified.json'); + + if (!fs.existsSync(dataPath)) { + return {}; + } + + const data = fs.readFileSync(dataPath, 'utf8'); + return JSON.parse(data); + } catch (error) { + console.error('读取文档修改时间数据失败:', error); + return {}; + } +} export default async function Page({ params @@ -20,6 +39,11 @@ export default async function Page({ const MDXContent = page.data.body; + // 获取文档的最后修改时间 + const docLastModifiedData = getDocLastModifiedData(); + const filePath = `content/docs/${page.file.path}`; + const lastModified = docLastModifiedData[filePath] || page.data.lastModified; + return ( {page.data.title} {page.data.description} diff --git a/document/components/docs/not-found.tsx b/document/components/docs/not-found.tsx index 67a2c2d2c..45979fad9 100644 --- a/document/components/docs/not-found.tsx +++ b/document/components/docs/not-found.tsx @@ -4,7 +4,7 @@ import { usePathname } from 'next/navigation'; import { useEffect } from 'react'; const exactMap: Record = { - '/docs/intro': '/docs/introduction/index', + '/docs/intro': '/docs/introduction', '/docs/guide/dashboard/workflow/coreferenceresolution': '/docs/introduction/guide/dashboard/workflow/coreferenceResolution', '/docs/guide/admin/sso_dingtalk': diff --git a/document/data/doc-last-modified.json b/document/data/doc-last-modified.json new file mode 100644 index 000000000..5570e94fe --- /dev/null +++ b/document/data/doc-last-modified.json @@ -0,0 +1,187 @@ +{ + "content/docs/api/api1.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/api/api2.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/api/index.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/index.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/FAQ/app.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/chat.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/dataset.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/docker.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/error.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/external_channel_integration.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/other.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/points_consumption.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/FAQ/privateDeploy.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/community.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/configuration.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/bge-rerank.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/chatglm2-m3e.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/chatglm2.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/m3e.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/marker.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/ollama.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/custom-models/xinference.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/design/dataset.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/design/design_plugin.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/docker.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/faq.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/intro.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/migration/docker_db.mdx": "2025-07-16T18:34:52+08:00", + "content/docs/introduction/development/migration/docker_mongo.mdx": "2025-07-16T18:34:52+08:00", + "content/docs/introduction/development/modelConfig/ai-proxy.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/modelConfig/intro.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/modelConfig/one-api.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/modelConfig/ppio.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/modelConfig/siliconCloud.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/openapi/chat.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/openapi/dataset.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/openapi/intro.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/openapi/share.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/development/proxy/cloudflare.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/proxy/http_proxy.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/proxy/nginx.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/sealos.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/40.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/41.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4100.mdx": "2025-07-16T18:34:52+08:00", + "content/docs/introduction/development/upgrading/4101.mdx": "2025-07-16T18:34:52+08:00", + "content/docs/introduction/development/upgrading/42.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/421.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/43.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/44.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/441.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/442.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/445.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/446.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/447.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/45.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/451.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/452.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/46.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/461.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/462.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/463.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/464.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/465.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/466.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/467.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/468.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/469.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/47.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/471.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/48.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/481.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4810.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4811.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4812.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4813.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4814.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4815.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4816.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4817.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4818.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4819.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/482.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4820.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4821.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4822.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4823.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/483.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/484.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/485.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/486.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/487.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/488.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/489.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/490.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/491.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4910.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4911.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4912.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4913.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/4914.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/492.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/493.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/494.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/495.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/496.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/497.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/498.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/499.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/development/upgrading/intro.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/DialogBoxes/htmlRendering.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/DialogBoxes/quoteList.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/admin/sso.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/guide/admin/teamMode.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/course/ai_settings.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/course/chat_input_guide.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/course/collection_tags.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/course/fileInput.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/course/quick-start.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/basic-mode.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/gapier.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/intro.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/mcp_server.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/mcp_tools.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/ai_chat.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/content_extract.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/coreferenceResolution.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/custom_feedback.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/dataset_search.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/document_parsing.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/form_input.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/http.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/guide/dashboard/workflow/knowledge_base_search_merge.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/laf.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/loop.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/question_classify.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/reply.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/sandbox.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/text_editor.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/tfswitch.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/tool.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/user-selection.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/dashboard/workflow/variable_update.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/RAG.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/api_dataset.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/guide/knowledge_base/dataset_engine.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/externalFile.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/lark_dataset.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/template.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/third_dataset.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/websync.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/knowledge_base/yuque_dataset.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/plugins/bing_search_plugin.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/plugins/dev_system_tool.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/plugins/doc2x_plugin_guide.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/plugins/google_search_plugin_guide.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/plugins/how_to_submit_system_plugin.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/plugins/searxng_plugin_guide.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/team_permissions/invitation_link.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/guide/team_permissions/team_roles_permissions.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/index.en.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/index.mdx": "2025-07-17T19:11:49+08:00", + "content/docs/introduction/shopping_cart/intro.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/introduction/shopping_cart/saas.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/index.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/open-source.en.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/open-source.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/privacy.en.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/privacy.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/terms.en.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/protocol/terms.mdx": "2025-07-15T15:23:52+08:00", + "content/docs/use-cases/app-cases/dalle3.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/english_essay_correction_bot.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/feishu_webhook.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/fixingEvidence.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/google_search.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/lab_appointment.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/multi_turn_translation_bot.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/submit_application_template.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/app-cases/translate-subtitle-using-gpt.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/external-integration/dingtalk.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/external-integration/feishu.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/external-integration/official_account.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/external-integration/openapi.mdx": "2025-05-15T10:53:31+08:00", + "content/docs/use-cases/index.mdx": "2025-07-16T18:34:52+08:00" +} \ No newline at end of file diff --git a/document/github.js b/document/github.js new file mode 100644 index 000000000..a7405a29f --- /dev/null +++ b/document/github.js @@ -0,0 +1,182 @@ +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +/** + * 获取文件的 git 最后修改时间 + * @param {string} filePath - 文件路径 + * @returns {string|null} - 最后修改时间(ISO 格式)或 null + */ + +function getFileLastModifiedTime(filePath) { + try { + // 使用 git log 获取文件的最后修改时间 + const command = `git log -1 --format="%aI" -- "${filePath}"`; + const result = execSync(command, { + encoding: 'utf8', + cwd: process.cwd(), + stdio: ['pipe', 'pipe', 'pipe'] + }); + + return result.trim() || null; + } catch (error) { + console.warn(`无法获取文件 ${filePath} 的 git 信息:`, error.message); + return null; + } +} + +/** + * 递归获取目录下所有文档文件 + * @param {string} dirPath - 目录路径 + * @param {string[]} extensions - 文件扩展名数组 + * @returns {string[]} - 文件路径数组 + */ +function getAllDocFiles(dirPath, extensions = ['.md', '.mdx']) { + const files = []; + + function traverse(currentPath) { + const items = fs.readdirSync(currentPath); + + for (const item of items) { + const fullPath = path.join(currentPath, item); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + // 跳过 node_modules 和 .git 目录 + if (item !== 'node_modules' && item !== '.git' && !item.startsWith('.')) { + traverse(fullPath); + } + } else if (stat.isFile()) { + const ext = path.extname(item); + if (extensions.includes(ext)) { + files.push(fullPath); + } + } + } + } + + traverse(dirPath); + return files; +} + +/** + * 获取所有文档的最新修改时间 + * @param {string} contentDir - 文档内容目录 + * @returns {Object} - 文件路径到修改时间的映射 + */ +function getAllDocLastModifiedTimes(contentDir = './document/content/docs') { + const docFiles = getAllDocFiles(contentDir); + const result = {}; + + console.log(`正在处理 ${docFiles.length} 个文档文件...`); + + for (const filePath of docFiles) { + const relativePath = path.relative(process.cwd(), filePath); + const lastModified = getFileLastModifiedTime(relativePath); + + if (lastModified) { + result[relativePath] = lastModified; + } + + // 显示进度 + process.stdout.write('.'); + } + + console.log('\n完成!'); + return result; +} + +/** + * 将结果保存到 JSON 文件 + * @param {Object} data - 要保存的数据 + * @param {string} outputPath - 输出文件路径 + */ +function saveToJsonFile(data, outputPath = './document/data/doc-last-modified.json') { + try { + // 确保目录存在 + const dir = path.dirname(outputPath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), 'utf8'); + console.log(`结果已保存到: ${outputPath}`); + } catch (error) { + console.error('保存文件失败:', error.message); + } +} + +/** + * 获取单个文件的详细信息 + * @param {string} filePath - 文件路径 + * @returns {Object} - 文件信息对象 + */ +function getFileInfo(filePath) { + const relativePath = path.relative(process.cwd(), filePath); + const lastModified = getFileLastModifiedTime(relativePath); + const stat = fs.statSync(filePath); + + return { + path: relativePath, + lastModified, + size: stat.size, + created: stat.birthtime.toISOString(), + modified: stat.mtime.toISOString() + }; +} + +/** + * 主函数 - 获取所有文档的最新修改时间并保存 + */ +function main() { + console.log('开始获取文档的最新修改时间...'); + + let contentDir = process.argv[2]; + + // 如果没有传参数,或者传入的是文件而非目录,就使用默认目录 + if (!contentDir || !fs.existsSync(contentDir) || !fs.statSync(contentDir).isDirectory()) { + contentDir = './document/content/docs'; + } + + if (!fs.existsSync(contentDir)) { + console.error(`目录不存在: ${contentDir}`); + process.exit(1); + } + + const result = getAllDocLastModifiedTimes(contentDir); + + // 保存简单的文件路径到修改时间的映射 + saveToJsonFile(result, './document/data/doc-last-modified.json'); + + // 显示统计信息 + console.log('\n统计信息:'); + console.log(`- 总文件数: ${Object.keys(result).length}`); + console.log(`- 成功获取时间: ${Object.values(result).filter(Boolean).length}`); + console.log(`- 失败文件数: ${Object.values(result).filter((v) => !v).length}`); + + // 显示最近修改的文件 + const recentFiles = Object.entries(result) + .filter(([, time]) => time) + .sort(([, a], [, b]) => new Date(b) - new Date(a)) + .slice(0, 5); + + if (recentFiles.length > 0) { + console.log('\n最近修改的文件:'); + recentFiles.forEach(([file, time]) => { + console.log(`- ${file}: ${new Date(time).toLocaleString()}`); + }); + } +} + +// 如果直接运行此文件 +if (require.main === module) { + main(); +} + +module.exports = { + getFileLastModifiedTime, + getAllDocFiles, + getAllDocLastModifiedTimes, + getFileInfo, + saveToJsonFile +}; diff --git a/document/package.json b/document/package.json index c68784b7e..2b62665e3 100644 --- a/document/package.json +++ b/document/package.json @@ -6,6 +6,7 @@ "build": "next build", "update-index-action": "node ./update-index.mjs", "update-index": "node --env-file=.env.local ./update-index.mjs", + "get-doc-times": "node ./github.js", "dev": "next dev --turbo", "start": "next start", "postinstall": "fumadocs-mdx" diff --git a/package.json b/package.json index 5de868cb0..6674c548f 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "format-code": "prettier --config \"./.prettierrc.js\" --write \"./**/src/**/*.{ts,tsx,scss}\"", "format-doc": "zhlint --dir ./document/ *.mdx --fix", "gen:theme-typings": "chakra-cli tokens packages/web/styles/theme.ts --out node_modules/.pnpm/node_modules/@chakra-ui/styled-system/dist/theming.types.d.ts", + "initLastModified": "node ./document/github.js", "postinstall": "pnpm gen:theme-typings", "initIcon": "node ./scripts/icon/init.js", "previewIcon": "node ./scripts/icon/index.js", @@ -41,7 +42,11 @@ "./**/**/*.{ts,tsx}": [ "pnpm lint" ], - "./document/**/**/*.md": "pnpm format-doc" + "./document/**/**/*.mdx": [ + "pnpm format-doc", + "pnpm initLastModified", + "git add ." + ] }, "resolutions": { "mdast-util-gfm-autolink-literal": "2.0.0"