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:
+124
@@ -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 图片",
|
||||
|
||||
Reference in New Issue
Block a user