feat: implement dynamic changelog loading from API

- Add GET /api/changelog endpoint to fetch changelog from CHANGELOG.md
- Create service/changelog.go to parse CHANGELOG.md markdown file
- Add handler/changelog.go to handle changelog requests
- Update ChangelogDrawer component to fetch from API instead of hardcoded data
- Export apiFetch from lib/api.ts for public use
- Add changelog parser tests with 14 version entries verified
This commit is contained in:
clz
2026-04-02 17:52:38 +08:00
parent c4d8c2e105
commit ee163e123d
9 changed files with 259 additions and 80 deletions

View File

@@ -5,7 +5,7 @@ import type { UIBill } from '$lib/models/bill';
// API 配置 - 使用相对路径,由 SvelteKit 代理到后端
const API_BASE = '';
async function apiFetch(input: RequestInfo | URL, init: RequestInit = {}) {
export async function apiFetch(input: RequestInfo | URL, init: RequestInit = {}) {
const headers = new Headers(init.headers);
if (browser) {

View File

@@ -3,77 +3,48 @@
import { Button } from '$lib/components/ui/button';
import Calendar from '@lucide/svelte/icons/calendar';
import Tag from '@lucide/svelte/icons/tag';
import { onMount } from 'svelte';
import { apiFetch } from '$lib/api';
let { open = $bindable(false) } = $props();
// Changelog 内容(从 CHANGELOG.md 解析或硬编码)
const changelog = [
{
version: '1.3.1',
date: '2026-01-26',
changes: {
优化: [
'版本号显示优化 - 侧边栏版本号按钮样式改进',
'移至次级导航区域,与其他菜单项样式一致',
'更新日志改用 Sheet 组件(右侧滑出),替代底部 Drawer',
'统一暗色主题下的视觉效果'
]
interface ChangelogEntry {
version: string;
date: string;
changes: Record<string, string[]>;
}
let changelog = $state<ChangelogEntry[]>([]);
let isLoading = $state(false);
let error = $state<string | null>(null);
// 获取更新日志
async function fetchChangelog() {
isLoading = true;
error = null;
try {
const response = await apiFetch('/api/changelog');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
},
{
version: '1.3.0',
date: '2026-01-26',
changes: {
新增: [
'京东账单支持 - 支持京东白条账单上传和清洗',
'自动识别京东账单类型(交易流水 ZIP',
'解析京东白条账单 CSV 格式(含还款日期信息)',
'京东专属分类映射配置',
'支持京东外卖、京东平台商户等商户识别',
'上传页面和账单列表页面添加"京东"选项'
],
优化: [
'京东订单智能去重 - 上传京东账单时自动软删除其他来源中的京东订单',
'分类推断复核等级优化 - 京东账单引入 LOW 复核等级',
'京东平台商户关键词扩展'
],
技术改进: [
'新增京东账单清理器',
'新增京东专属配置',
'后端新增软删除接口',
'新增单元测试11 个测试用例)'
]
}
},
{
version: '1.2.1',
date: '2026-01-23',
changes: {
优化: [
'智能复核快捷确认 - 在复核列表每行添加快捷确认按钮',
'无需打开详情页面即可确认分类正确',
'自动更新统计数据',
'提升复核效率,支持快速批量确认'
],
文档: ['AGENTS.md 更新 - 精简为 150 行,专为 AI 编程助手设计']
}
},
{
version: '1.2.0',
date: '2026-01-25',
changes: {
新增: [
'账单删除功能 - 支持在账单详情抽屉中删除账单(软删除)',
'删除按钮带二次确认,防止误操作',
'已删除的账单在所有查询中自动过滤'
],
技术改进: [
'后端 MongoDB 查询方法添加软删除过滤',
'新增 DELETE /api/bills/:id 接口'
]
const data = await response.json();
if (data.result && Array.isArray(data.data)) {
changelog = data.data;
} else {
throw new Error('Invalid response format');
}
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to fetch changelog';
console.error('Failed to fetch changelog:', err);
} finally {
isLoading = false;
}
];
}
// 组件挂载时获取数据
onMount(() => {
fetchChangelog();
});
</script>
<Sheet.Root bind:open>
@@ -85,7 +56,20 @@
</Sheet.Description>
</Sheet.Header>
<div class="flex-1 overflow-y-auto py-6">
<div class="flex-1 overflow-y-auto py-6">
{#if isLoading}
<div class="flex items-center justify-center py-8">
<div class="text-muted-foreground">加载中...</div>
</div>
{:else if error}
<div class="flex items-center justify-center py-8">
<div class="text-destructive text-sm">{error}</div>
</div>
{:else if changelog.length === 0}
<div class="flex items-center justify-center py-8">
<div class="text-muted-foreground">暂无更新日志</div>
</div>
{:else}
<div class="space-y-8">
{#each changelog as release}
<div class="space-y-3">
@@ -120,7 +104,8 @@
</div>
{/each}
</div>
</div>
{/if}
</div>
<Sheet.Footer class="border-t pt-4">
<Button variant="outline" onclick={() => (open = false)} class="w-full">关闭</Button>