feat: implement tag management and search functionality

Features:
- Tag system with multi-language support (Chinese/English)
- Auto-create tags when associating with articles
- Tag filtering on homepage with visual indicators
- Full-text search across title, summary, and content
- Tag cloud sidebar showing article counts
- Search page with results display

Technical Implementation:
- Database models: Tag, ArticleTag (many-to-many)
- Tag count caching for performance
- Automatic tag slug generation
- Responsive design with mobile support
- I18n support for all new UI elements

Bug Fix:
- Fixed SQL column ambiguity error in tag filtering
- Added table prefix to ORDER BY clause in publishedArticleOrder

Routes:
- GET /search - Search results page
- GET /?tag=<slug> - Filter articles by tag
- GET /api/articles?tag=<slug> - API with tag filter support

Templates:
- Added tag input field to article create/edit form
- Added search box to homepage header
- Added tag cloud sidebar on homepage and search page
- Created new search results page template

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 20:59:32 +08:00
co-authored by Claude Fable 5
parent b4983f1d4d
commit 2bdc368399
14 changed files with 1611 additions and 12 deletions
+124
View File
@@ -46,6 +46,38 @@ var translations = map[Lang]map[string]string{
"login_submit": "Sign In",
"login_error": "Invalid username or password.",
"login_required": "Please fill in all fields.",
"login_no_account": "Don't have an account?",
"login_register_link": "Register",
// Register page
"page_register": "Register",
"register_title": "Create Account",
"register_username": "Username",
"register_ph_username": "Choose a username",
"register_username_hint": "3-32 characters, letters, numbers, underscore and dash only",
"register_display_name": "Display Name",
"register_ph_display_name": "Your display name",
"register_display_name_hint": "Optional, defaults to username if empty",
"register_email": "Email",
"register_ph_email": "Your email address",
"register_email_hint": "Optional, used for Gravatar avatar",
"register_password": "Password",
"register_ph_password": "Choose a password",
"register_password_hint": "At least 6 characters",
"register_confirm_password": "Confirm Password",
"register_ph_confirm_password": "Re-enter your password",
"register_submit": "Register",
"register_have_account": "Already have an account?",
"register_login_link": "Sign In",
"register_required": "Username and password are required.",
"register_username_length": "Username must be 3-32 characters.",
"register_password_length": "Password must be at least 6 characters.",
"register_password_mismatch": "Passwords do not match.",
"register_error": "Registration failed. Please try again.",
// Settings
"settings_allow_registration": "Allow user registration",
"settings_allow_registration_hint": "When enabled, visitors can create their own accounts from the login page",
// Dashboard
"dash_title": "Dashboard",
@@ -164,11 +196,41 @@ var translations = map[Lang]map[string]string{
"article_col_actions": "Actions",
"article_last_updated": "Last Updated",
// Tags
"tags_title": "Tags",
"article_tags": "Tags",
"article_tags_hint": "Comma-separated tag names, e.g., golang, web, tutorial",
"tag_filter": "Filter by tag",
"tag_all": "All",
// Search
"search_placeholder": "Search articles...",
"search_title": "Search Results",
"search_results_for": "Search results for",
"search_no_results": "No articles found matching your search.",
"search_keyword": "Keyword",
// Settings (platform configuration)
"settings_nav": "Platform Settings",
"settings_saved": "Settings saved.",
"settings_site_title": "Site Settings",
"settings_site_desc": "Logo, top-left title, header banner, and footer text.",
"settings_navlinks_title": "Navigation Links",
"settings_navlinks_desc": "Manage custom links in the header navigation.",
"navlinks_add": "Add Link",
"navlinks_title_zh": "Link Text (Chinese)",
"navlinks_title_en": "Link Text (English)",
"navlinks_url": "URL",
"navlinks_url_hint": "Can be relative (/about) or absolute (https://example.com)",
"navlinks_open_new": "Open in new window",
"navlinks_enabled": "Enabled",
"navlinks_sort": "Sort Order",
"navlinks_edit": "Edit",
"navlinks_delete": "Delete",
"navlinks_confirm_delete": "Are you sure you want to delete this link?",
"navlinks_no_links": "No navigation links configured yet.",
"navlinks_save": "Save",
"navlinks_cancel": "Cancel",
"settings_logo": "Logo",
"settings_logo_url": "Logo URL (external link)",
"settings_logo_upload": "Or upload a logo image",
@@ -404,6 +466,38 @@ var translations = map[Lang]map[string]string{
"login_submit": "登录",
"login_error": "用户名或密码错误。",
"login_required": "请填写所有字段。",
"login_no_account": "还没有账号?",
"login_register_link": "注册",
// 注册页
"page_register": "注册",
"register_title": "创建账号",
"register_username": "用户名",
"register_ph_username": "请输入用户名",
"register_username_hint": "3-32个字符,仅限字母、数字、下划线和连字符",
"register_display_name": "显示名称",
"register_ph_display_name": "请输入显示名称",
"register_display_name_hint": "可选,留空则使用用户名",
"register_email": "邮箱",
"register_ph_email": "请输入邮箱地址",
"register_email_hint": "可选,用于显示 Gravatar 头像",
"register_password": "密码",
"register_ph_password": "请输入密码",
"register_password_hint": "至少6个字符",
"register_confirm_password": "确认密码",
"register_ph_confirm_password": "请再次输入密码",
"register_submit": "注册",
"register_have_account": "已有账号?",
"register_login_link": "登录",
"register_required": "用户名和密码不能为空。",
"register_username_length": "用户名必须是3-32个字符。",
"register_password_length": "密码至少需要6个字符。",
"register_password_mismatch": "两次输入的密码不一致。",
"register_error": "注册失败,请重试。",
// 平台设置
"settings_allow_registration": "允许用户注册",
"settings_allow_registration_hint": "启用后,访客可以从登录页面创建自己的账号",
// 后台
"dash_title": "后台管理",
@@ -520,11 +614,41 @@ var translations = map[Lang]map[string]string{
"article_col_actions": "操作",
"article_last_updated": "最后更新",
// 标签
"tags_title": "标签",
"article_tags": "标签",
"article_tags_hint": "逗号分隔的标签名称,例如:golang, web, 教程",
"tag_filter": "按标签筛选",
"tag_all": "全部",
// 搜索
"search_placeholder": "搜索文章...",
"search_title": "搜索结果",
"search_results_for": "搜索结果",
"search_no_results": "未找到匹配的文章。",
"search_keyword": "关键词",
// 平台设置
"settings_nav": "平台设置",
"settings_saved": "设置已保存。",
"settings_site_title": "站点设置",
"settings_site_desc": "Logo、左上角标题、顶部横幅文本和页脚文本。",
"settings_navlinks_title": "导航链接",
"settings_navlinks_desc": "管理顶部导航栏的自定义链接。",
"navlinks_add": "添加链接",
"navlinks_title_zh": "链接文字(中文)",
"navlinks_title_en": "链接文字(英文)",
"navlinks_url": "链接地址",
"navlinks_url_hint": "可以是相对路径(/about)或完整链接(https://example.com",
"navlinks_open_new": "在新窗口打开",
"navlinks_enabled": "启用",
"navlinks_sort": "排序",
"navlinks_edit": "编辑",
"navlinks_delete": "删除",
"navlinks_confirm_delete": "确定要删除这个链接吗?",
"navlinks_no_links": "还没有配置导航链接。",
"navlinks_save": "保存",
"navlinks_cancel": "取消",
"settings_logo": "Logo",
"settings_logo_url": "Logo 链接(外链地址)",
"settings_logo_upload": "或上传 Logo 图片",