feat: Refactor service management scripts to use a unified dev script

- Added package.json to manage development scripts.
- Updated restart-services.ps1 to call the new dev script for starting services.
- Refactored start-admin.ps1, start-backend.ps1, start-frontend.ps1, and start-mcp.ps1 to utilize the dev script for starting respective services.
- Enhanced stop-services.ps1 to improve process termination logic by matching command patterns.
This commit is contained in:
2026-03-29 21:36:13 +08:00
parent 84f82c2a7e
commit 92a85eef20
137 changed files with 14181 additions and 2691 deletions

View File

@@ -11,15 +11,23 @@ import Lightbox from '../../components/Lightbox.astro';
import CodeCopyButton from '../../components/CodeCopyButton.astro';
import Comments from '../../components/Comments.astro';
import ParagraphComments from '../../components/ParagraphComments.astro';
import { apiClient } from '../../lib/api/client';
import { apiClient, DEFAULT_SITE_SETTINGS } from '../../lib/api/client';
import { formatReadTime, getI18n } from '../../lib/i18n';
import { resolveFileRef, getPostTypeColor } from '../../lib/utils';
import {
getAccentVars,
getCategoryTheme,
getPostTypeColor,
getPostTypeTheme,
getTagTheme,
resolveFileRef,
} from '../../lib/utils';
export const prerender = false;
const { slug } = Astro.params;
let post = null;
let siteSettings = DEFAULT_SITE_SETTINGS;
try {
post = await apiClient.getPostBySlug(slug ?? '');
@@ -27,22 +35,31 @@ try {
console.error('API Error:', error);
}
try {
siteSettings = await apiClient.getSiteSettings();
} catch (error) {
console.error('Site settings API Error:', error);
}
if (!post) {
return new Response(null, { status: 404 });
}
const typeColor = getPostTypeColor(post.type || 'article');
const typeTheme = getPostTypeTheme(post.type || 'article');
const categoryTheme = getCategoryTheme(post.category);
const contentText = post.content || post.description || '';
const wordCount = contentText.length;
const readTimeMinutes = Math.ceil(wordCount / 300);
const { locale, t } = getI18n(Astro);
const articleMarkdown = contentText.replace(/^#\s+.+\r?\n+/, '');
const paragraphCommentsEnabled = siteSettings.comments.paragraphsEnabled;
const markdownProcessor = await createMarkdownProcessor();
const renderedContent = await markdownProcessor.render(articleMarkdown);
---
<BaseLayout title={`${post.title} - Termi`} description={post.description}>
<BaseLayout title={post.title} description={post.description}>
<ReadingProgress />
<BackToTop />
<Lightbox />
@@ -66,12 +83,12 @@ const renderedContent = await markdownProcessor.render(articleMarkdown);
<i class="fas fa-file-code"></i>
{t('article.documentSession')}
</span>
<span class="terminal-chip">
<span class="terminal-chip terminal-chip--accent" style={getAccentVars(typeTheme)}>
<span class="h-2.5 w-2.5 rounded-full" style={`background-color: ${typeColor}`}></span>
{post.type === 'article' ? t('common.article') : t('common.tweet')}
</span>
<span class="terminal-chip">
<i class="fas fa-folder-tree text-[var(--primary)]"></i>
<span class="terminal-chip terminal-chip--accent" style={getAccentVars(categoryTheme)}>
<i class="fas fa-folder-tree"></i>
{post.category}
</span>
</div>
@@ -101,7 +118,11 @@ const renderedContent = await markdownProcessor.render(articleMarkdown);
{post.tags?.length > 0 && (
<div class="flex flex-wrap gap-2">
{post.tags.map(tag => (
<a href={`/tags?tag=${encodeURIComponent(tag)}`} class="terminal-filter">
<a
href={`/tags?tag=${encodeURIComponent(tag)}`}
class="terminal-filter"
style={getAccentVars(getTagTheme(tag))}
>
<i class="fas fa-hashtag"></i>
<span>{tag}</span>
</a>
@@ -120,18 +141,30 @@ const renderedContent = await markdownProcessor.render(articleMarkdown);
<img
src={resolveFileRef(post.image)}
alt={post.title}
data-lightbox-image="true"
class="w-full h-auto rounded-xl border border-[var(--border-color)] cursor-zoom-in"
/>
</div>
)}
<div class="terminal-document article-content" set:html={renderedContent.code}></div>
</div>
</div>
{post.images && post.images.length > 0 && (
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
{post.images.map((image, index) => (
<div class="terminal-panel-muted overflow-hidden">
<img
src={resolveFileRef(image)}
alt={`${post.title} 图片 ${index + 1}`}
data-lightbox-image="true"
class="h-full w-full rounded-xl border border-[var(--border-color)] object-cover cursor-zoom-in"
/>
</div>
))}
</div>
)}
<div class="px-4 pb-2">
<div class="ml-4 mt-4">
<ParagraphComments postSlug={post.slug} />
{paragraphCommentsEnabled && <ParagraphComments postSlug={post.slug} class="mb-4" />}
<div class="terminal-document article-content" set:html={renderedContent.code}></div>
</div>
</div>