From 8f0a49493caed39f188504637d5b7fa42b90c37b Mon Sep 17 00:00:00 2001 From: WrBug Date: Mon, 2 Mar 2026 22:02:00 +0800 Subject: [PATCH] =?UTF-8?q?refactor(notification):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E9=85=8D=E7=BD=AE=E5=B8=83=E5=B1=80=E5=B9=B6?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=A4=9A=E8=AF=AD=E8=A8=80=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 布局优化:模板类型改为顶部Tabs,内容区70%+变量面板30% - 变量Tag UI优化:更精致的样式和悬浮效果 - 多语言:添加模板类型描述、变量label/description的i18n key(三语言) - 后端精简:移除DTO中冗余的label/description/templateTypeName字段 - 清理:移除未使用的templates状态和fetchTemplates方法 Made-with: Cursor --- .../dto/NotificationTemplateDto.kt | 4 - .../system/NotificationTemplateService.kt | 137 +++++++++--------- frontend/src/locales/en/common.json | 55 ++++++- frontend/src/locales/zh-CN/common.json | 55 ++++++- frontend/src/locales/zh-TW/common.json | 55 ++++++- .../src/pages/NotificationSettingsPage.tsx | 136 +++++++---------- frontend/src/types/index.ts | 4 - 7 files changed, 284 insertions(+), 162 deletions(-) diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/dto/NotificationTemplateDto.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/dto/NotificationTemplateDto.kt index 9e1c42b..d406cb7 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/dto/NotificationTemplateDto.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/dto/NotificationTemplateDto.kt @@ -17,8 +17,6 @@ data class NotificationTemplateDto( */ data class TemplateVariableDto( val key: String, // 变量名,如 account_name - val label: String, // 显示名称,如 账户名称 - val description: String, // 变量说明 val category: String, // 分类:common, order, copy_trading, redeem, error val sortOrder: Int = 0 // 排序顺序 ) @@ -28,7 +26,6 @@ data class TemplateVariableDto( */ data class TemplateVariableCategoryDto( val key: String, // 分类 key - val label: String, // 分类名称 val sortOrder: Int = 0 // 排序顺序 ) @@ -37,7 +34,6 @@ data class TemplateVariableCategoryDto( */ data class TemplateVariablesResponse( val templateType: String, // 模板类型 - val templateTypeName: String, // 模板类型名称 val categories: List, // 分类列表 val variables: List // 变量列表 ) diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/NotificationTemplateService.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/NotificationTemplateService.kt index caf9225..dbc8870 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/NotificationTemplateService.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/NotificationTemplateService.kt @@ -56,104 +56,104 @@ class NotificationTemplateService( // 变量分类 val VARIABLE_CATEGORIES = listOf( - TemplateVariableCategoryDto("common", "通用变量", 0), - TemplateVariableCategoryDto("order", "订单变量", 10), - TemplateVariableCategoryDto("copy_trading", "跟单变量", 20), - TemplateVariableCategoryDto("redeem", "赎回变量", 30), - TemplateVariableCategoryDto("error", "错误变量", 40), - TemplateVariableCategoryDto("filter", "过滤变量", 50), - TemplateVariableCategoryDto("strategy", "策略变量", 60) + TemplateVariableCategoryDto("common", 0), + TemplateVariableCategoryDto("order", 10), + TemplateVariableCategoryDto("copy_trading", 20), + TemplateVariableCategoryDto("redeem", 30), + TemplateVariableCategoryDto("error", 40), + TemplateVariableCategoryDto("filter", 50), + TemplateVariableCategoryDto("strategy", 60) ) // 各模板类型可用的变量 val TEMPLATE_VARIABLES = mapOf( "ORDER_SUCCESS" to listOf( // 通用变量 - TemplateVariableDto("account_name", "账户名称", "执行订单的账户名称", "common", 1), - TemplateVariableDto("wallet_address", "钱包地址", "钱包地址(已脱敏)", "common", 2), - TemplateVariableDto("time", "时间", "通知发送时间", "common", 3), + TemplateVariableDto("account_name", "common", 1), + TemplateVariableDto("wallet_address", "common", 2), + TemplateVariableDto("time", "common", 3), // 订单变量 - TemplateVariableDto("order_id", "订单ID", "订单唯一标识", "order", 10), - TemplateVariableDto("market_title", "市场标题", "市场/事件名称", "order", 11), - TemplateVariableDto("market_link", "市场链接", "Polymarket 市场链接", "order", 12), - TemplateVariableDto("side", "方向", "订单方向(买入/卖出)", "order", 13), - TemplateVariableDto("outcome", "市场方向", "市场方向(YES/NO 等)", "order", 14), - TemplateVariableDto("price", "价格", "订单价格", "order", 15), - TemplateVariableDto("quantity", "数量", "订单数量(shares)", "order", 16), - TemplateVariableDto("amount", "金额", "订单金额(USDC)", "order", 17), - TemplateVariableDto("available_balance", "可用余额", "账户可用余额(USDC)", "order", 18), + TemplateVariableDto("order_id", "order", 10), + TemplateVariableDto("market_title", "order", 11), + TemplateVariableDto("market_link", "order", 12), + TemplateVariableDto("side", "order", 13), + TemplateVariableDto("outcome", "order", 14), + TemplateVariableDto("price", "order", 15), + TemplateVariableDto("quantity", "order", 16), + TemplateVariableDto("amount", "order", 17), + TemplateVariableDto("available_balance", "order", 18), // 跟单变量 - TemplateVariableDto("leader_name", "Leader 名称", "跟单的 Leader 名称/备注", "copy_trading", 21), - TemplateVariableDto("config_name", "跟单配置名", "跟单配置名称", "copy_trading", 22) + TemplateVariableDto("leader_name", "copy_trading", 21), + TemplateVariableDto("config_name", "copy_trading", 22) ), "ORDER_FAILED" to listOf( // 通用变量 - TemplateVariableDto("account_name", "账户名称", "执行订单的账户名称", "common", 1), - TemplateVariableDto("wallet_address", "钱包地址", "钱包地址(已脱敏)", "common", 2), - TemplateVariableDto("time", "时间", "通知发送时间", "common", 3), + TemplateVariableDto("account_name", "common", 1), + TemplateVariableDto("wallet_address", "common", 2), + TemplateVariableDto("time", "common", 3), // 订单变量 - TemplateVariableDto("market_title", "市场标题", "市场/事件名称", "order", 10), - TemplateVariableDto("market_link", "市场链接", "Polymarket 市场链接", "order", 11), - TemplateVariableDto("side", "方向", "订单方向(买入/卖出)", "order", 12), - TemplateVariableDto("outcome", "市场方向", "市场方向(YES/NO 等)", "order", 13), - TemplateVariableDto("price", "价格", "订单价格", "order", 14), - TemplateVariableDto("quantity", "数量", "订单数量(shares)", "order", 15), - TemplateVariableDto("amount", "金额", "订单金额(USDC)", "order", 16), + TemplateVariableDto("market_title", "order", 10), + TemplateVariableDto("market_link", "order", 11), + TemplateVariableDto("side", "order", 12), + TemplateVariableDto("outcome", "order", 13), + TemplateVariableDto("price", "order", 14), + TemplateVariableDto("quantity", "order", 15), + TemplateVariableDto("amount", "order", 16), // 错误变量 - TemplateVariableDto("error_message", "错误信息", "订单失败原因", "error", 20) + TemplateVariableDto("error_message", "error", 20) ), "ORDER_FILTERED" to listOf( // 通用变量 - TemplateVariableDto("account_name", "账户名称", "执行订单的账户名称", "common", 1), - TemplateVariableDto("wallet_address", "钱包地址", "钱包地址(已脱敏)", "common", 2), - TemplateVariableDto("time", "时间", "通知发送时间", "common", 3), + TemplateVariableDto("account_name", "common", 1), + TemplateVariableDto("wallet_address", "common", 2), + TemplateVariableDto("time", "common", 3), // 订单变量 - TemplateVariableDto("market_title", "市场标题", "市场/事件名称", "order", 10), - TemplateVariableDto("market_link", "市场链接", "Polymarket 市场链接", "order", 11), - TemplateVariableDto("side", "方向", "订单方向(买入/卖出)", "order", 12), - TemplateVariableDto("outcome", "市场方向", "市场方向(YES/NO 等)", "order", 13), - TemplateVariableDto("price", "价格", "订单价格", "order", 14), - TemplateVariableDto("quantity", "数量", "订单数量(shares)", "order", 15), - TemplateVariableDto("amount", "金额", "订单金额(USDC)", "order", 16), + TemplateVariableDto("market_title", "order", 10), + TemplateVariableDto("market_link", "order", 11), + TemplateVariableDto("side", "order", 12), + TemplateVariableDto("outcome", "order", 13), + TemplateVariableDto("price", "order", 14), + TemplateVariableDto("quantity", "order", 15), + TemplateVariableDto("amount", "order", 16), // 过滤变量 - TemplateVariableDto("filter_type", "过滤类型", "订单被过滤的类型", "filter", 20), - TemplateVariableDto("filter_reason", "过滤原因", "订单被过滤的详细原因", "filter", 21) + TemplateVariableDto("filter_type", "filter", 20), + TemplateVariableDto("filter_reason", "filter", 21) ), "CRYPTO_TAIL_SUCCESS" to listOf( // 通用变量 - TemplateVariableDto("account_name", "账户名称", "执行订单的账户名称", "common", 1), - TemplateVariableDto("wallet_address", "钱包地址", "钱包地址(已脱敏)", "common", 2), - TemplateVariableDto("time", "时间", "通知发送时间", "common", 3), + TemplateVariableDto("account_name", "common", 1), + TemplateVariableDto("wallet_address", "common", 2), + TemplateVariableDto("time", "common", 3), // 订单变量 - TemplateVariableDto("order_id", "订单ID", "订单唯一标识", "order", 10), - TemplateVariableDto("market_title", "市场标题", "市场/事件名称", "order", 11), - TemplateVariableDto("market_link", "市场链接", "Polymarket 市场链接", "order", 12), - TemplateVariableDto("side", "方向", "订单方向(买入/卖出)", "order", 13), - TemplateVariableDto("outcome", "市场方向", "市场方向(YES/NO 等)", "order", 14), - TemplateVariableDto("price", "价格", "订单价格", "order", 15), - TemplateVariableDto("quantity", "数量", "订单数量(shares)", "order", 16), - TemplateVariableDto("amount", "金额", "订单金额(USDC)", "order", 17), + TemplateVariableDto("order_id", "order", 10), + TemplateVariableDto("market_title", "order", 11), + TemplateVariableDto("market_link", "order", 12), + TemplateVariableDto("side", "order", 13), + TemplateVariableDto("outcome", "order", 14), + TemplateVariableDto("price", "order", 15), + TemplateVariableDto("quantity", "order", 16), + TemplateVariableDto("amount", "order", 17), // 策略变量 - TemplateVariableDto("strategy_name", "策略名称", "加密价差策略名称", "strategy", 20) + TemplateVariableDto("strategy_name", "strategy", 20) ), "REDEEM_SUCCESS" to listOf( // 通用变量 - TemplateVariableDto("account_name", "账户名称", "执行赎回的账户名称", "common", 1), - TemplateVariableDto("wallet_address", "钱包地址", "钱包地址(已脱敏)", "common", 2), - TemplateVariableDto("time", "时间", "通知发送时间", "common", 3), + TemplateVariableDto("account_name", "common", 1), + TemplateVariableDto("wallet_address", "common", 2), + TemplateVariableDto("time", "common", 3), // 赎回变量 - TemplateVariableDto("transaction_hash", "交易哈希", "赎回交易的哈希值", "redeem", 10), - TemplateVariableDto("total_value", "赎回总价值", "赎回的总价值(USDC)", "redeem", 11), - TemplateVariableDto("available_balance", "可用余额", "账户可用余额(USDC)", "redeem", 12) + TemplateVariableDto("transaction_hash", "redeem", 10), + TemplateVariableDto("total_value", "redeem", 11), + TemplateVariableDto("available_balance", "redeem", 12) ), "REDEEM_NO_RETURN" to listOf( // 通用变量 - TemplateVariableDto("account_name", "账户名称", "执行赎回的账户名称", "common", 1), - TemplateVariableDto("wallet_address", "钱包地址", "钱包地址(已脱敏)", "common", 2), - TemplateVariableDto("time", "时间", "通知发送时间", "common", 3), + TemplateVariableDto("account_name", "common", 1), + TemplateVariableDto("wallet_address", "common", 2), + TemplateVariableDto("time", "common", 3), // 赎回变量 - TemplateVariableDto("transaction_hash", "交易哈希", "赎回交易的哈希值", "redeem", 10), - TemplateVariableDto("available_balance", "可用余额", "账户可用余额(USDC)", "redeem", 11) + TemplateVariableDto("transaction_hash", "redeem", 10), + TemplateVariableDto("available_balance", "redeem", 11) ) ) @@ -285,7 +285,7 @@ class NotificationTemplateService( * 获取模板可用变量 */ fun getTemplateVariables(templateType: String): TemplateVariablesResponse? { - val typeInfo = TEMPLATE_TYPES[templateType] ?: return null + if (!TEMPLATE_TYPES.containsKey(templateType)) return null val variables = TEMPLATE_VARIABLES[templateType] ?: emptyList() // 获取使用的分类 @@ -294,7 +294,6 @@ class NotificationTemplateService( return TemplateVariablesResponse( templateType = templateType, - templateTypeName = typeInfo.name, categories = categories, variables = variables ) diff --git a/frontend/src/locales/en/common.json b/frontend/src/locales/en/common.json index 3f5db71..48dae45 100644 --- a/frontend/src/locales/en/common.json +++ b/frontend/src/locales/en/common.json @@ -1193,7 +1193,52 @@ "redeemVariables": "Redeem Variables", "errorVariables": "Error Variables", "filterVariables": "Filter Variables", - "strategyVariables": "Strategy Variables" + "strategyVariables": "Strategy Variables", + "contentPlaceholder": "Enter template content here, use {{variable}} to insert dynamic content", + "variableLabels": { + "account_name": "Account Name", + "wallet_address": "Wallet Address", + "time": "Time", + "order_id": "Order ID", + "market_title": "Market Title", + "market_link": "Market Link", + "side": "Side", + "outcome": "Outcome", + "price": "Price", + "quantity": "Quantity", + "amount": "Amount", + "available_balance": "Available Balance", + "leader_name": "Leader Name", + "config_name": "Copy Trading Config Name", + "error_message": "Error Message", + "filter_type": "Filter Type", + "filter_reason": "Filter Reason", + "strategy_name": "Strategy Name", + "transaction_hash": "Transaction Hash", + "total_value": "Total Redeem Value" + }, + "variableDescriptions": { + "account_name": "Account name executing the order", + "wallet_address": "Wallet address (masked)", + "time": "Notification send time", + "order_id": "Unique order identifier", + "market_title": "Market/Event name", + "market_link": "Polymarket market link", + "side": "Order direction (Buy/Sell)", + "outcome": "Market outcome (YES/NO, etc.)", + "price": "Order price", + "quantity": "Order quantity (shares)", + "amount": "Order amount (USDC)", + "available_balance": "Account available balance (USDC)", + "leader_name": "Leader name/alias being copied", + "config_name": "Copy trading configuration name", + "error_message": "Order failure reason", + "filter_type": "Type of order filter", + "filter_reason": "Detailed reason for order filtering", + "strategy_name": "Crypto spread strategy name", + "transaction_hash": "Redeem transaction hash", + "total_value": "Total redeem value (USDC)" + } }, "templateTypes": { "ORDER_SUCCESS": "Order Success", @@ -1202,6 +1247,14 @@ "CRYPTO_TAIL_SUCCESS": "Crypto Spread Strategy Success", "REDEEM_SUCCESS": "Position Redeem Success", "REDEEM_NO_RETURN": "Position Settled (No Return)" + }, + "templateTypeDescriptions": { + "ORDER_SUCCESS": "Notification sent when order is successfully created", + "ORDER_FAILED": "Notification sent when order creation fails", + "ORDER_FILTERED": "Notification sent when order is filtered by risk control", + "CRYPTO_TAIL_SUCCESS": "Notification sent when crypto spread strategy order succeeds", + "REDEEM_SUCCESS": "Notification sent when position is successfully redeemed", + "REDEEM_NO_RETURN": "Notification sent when position is settled with no return" } }, "telegramConfig": { diff --git a/frontend/src/locales/zh-CN/common.json b/frontend/src/locales/zh-CN/common.json index 452234e..a39316d 100644 --- a/frontend/src/locales/zh-CN/common.json +++ b/frontend/src/locales/zh-CN/common.json @@ -1193,7 +1193,52 @@ "redeemVariables": "赎回变量", "errorVariables": "错误变量", "filterVariables": "过滤变量", - "strategyVariables": "策略变量" + "strategyVariables": "策略变量", + "contentPlaceholder": "在此输入模板内容,使用 {{变量名}} 插入动态内容", + "variableLabels": { + "account_name": "账户名称", + "wallet_address": "钱包地址", + "time": "时间", + "order_id": "订单ID", + "market_title": "市场标题", + "market_link": "市场链接", + "side": "方向", + "outcome": "市场方向", + "price": "价格", + "quantity": "数量", + "amount": "金额", + "available_balance": "可用余额", + "leader_name": "Leader 名称", + "config_name": "跟单配置名", + "error_message": "错误信息", + "filter_type": "过滤类型", + "filter_reason": "过滤原因", + "strategy_name": "策略名称", + "transaction_hash": "交易哈希", + "total_value": "赎回总价值" + }, + "variableDescriptions": { + "account_name": "执行订单的账户名称", + "wallet_address": "钱包地址(已脱敏)", + "time": "通知发送时间", + "order_id": "订单唯一标识", + "market_title": "市场/事件名称", + "market_link": "Polymarket 市场链接", + "side": "订单方向(买入/卖出)", + "outcome": "市场方向(YES/NO 等)", + "price": "订单价格", + "quantity": "订单数量(shares)", + "amount": "订单金额(USDC)", + "available_balance": "账户可用余额(USDC)", + "leader_name": "跟单的 Leader 名称/备注", + "config_name": "跟单配置名称", + "error_message": "订单失败原因", + "filter_type": "订单被过滤的类型", + "filter_reason": "订单被过滤的详细原因", + "strategy_name": "加密价差策略名称", + "transaction_hash": "赎回交易的哈希值", + "total_value": "赎回的总价值(USDC)" + } }, "templateTypes": { "ORDER_SUCCESS": "订单成功通知", @@ -1202,6 +1247,14 @@ "CRYPTO_TAIL_SUCCESS": "加密价差策略成功通知", "REDEEM_SUCCESS": "仓位赎回成功通知", "REDEEM_NO_RETURN": "仓位结算(无收益)通知" + }, + "templateTypeDescriptions": { + "ORDER_SUCCESS": "订单创建成功时发送的通知", + "ORDER_FAILED": "订单创建失败时发送的通知", + "ORDER_FILTERED": "订单被风控过滤时发送的通知", + "CRYPTO_TAIL_SUCCESS": "加密价差策略下单成功时发送的通知", + "REDEEM_SUCCESS": "仓位赎回成功时发送的通知", + "REDEEM_NO_RETURN": "仓位结算但无收益时发送的通知" } }, "telegramConfig": { diff --git a/frontend/src/locales/zh-TW/common.json b/frontend/src/locales/zh-TW/common.json index a2d7f9d..beebeaa 100644 --- a/frontend/src/locales/zh-TW/common.json +++ b/frontend/src/locales/zh-TW/common.json @@ -1193,7 +1193,52 @@ "redeemVariables": "贖回變量", "errorVariables": "錯誤變量", "filterVariables": "過濾變量", - "strategyVariables": "策略變量" + "strategyVariables": "策略變量", + "contentPlaceholder": "在此輸入模板內容,使用 {{變量名}} 插入動態內容", + "variableLabels": { + "account_name": "賬戶名稱", + "wallet_address": "錢包地址", + "time": "時間", + "order_id": "訂單ID", + "market_title": "市場標題", + "market_link": "市場鏈接", + "side": "方向", + "outcome": "市場方向", + "price": "價格", + "quantity": "數量", + "amount": "金額", + "available_balance": "可用餘額", + "leader_name": "Leader 名稱", + "config_name": "跟單配置名", + "error_message": "錯誤信息", + "filter_type": "過濾類型", + "filter_reason": "過濾原因", + "strategy_name": "策略名稱", + "transaction_hash": "交易哈希", + "total_value": "贖回總價值" + }, + "variableDescriptions": { + "account_name": "執行訂單的賬戶名稱", + "wallet_address": "錢包地址(已脫敏)", + "time": "通知發送時間", + "order_id": "訂單唯一標識", + "market_title": "市場/事件名稱", + "market_link": "Polymarket 市場鏈接", + "side": "訂單方向(買入/賣出)", + "outcome": "市場方向(YES/NO 等)", + "price": "訂單價格", + "quantity": "訂單數量(shares)", + "amount": "訂單金額(USDC)", + "available_balance": "賬戶可用餘額(USDC)", + "leader_name": "跟單的 Leader 名稱/備註", + "config_name": "跟單配置名稱", + "error_message": "訂單失敗原因", + "filter_type": "訂單被過濾的類型", + "filter_reason": "訂單被過濾的詳細原因", + "strategy_name": "加密價差策略名稱", + "transaction_hash": "贖回交易的哈希值", + "total_value": "贖回的總價值(USDC)" + } }, "templateTypes": { "ORDER_SUCCESS": "訂單成功通知", @@ -1202,6 +1247,14 @@ "CRYPTO_TAIL_SUCCESS": "加密價差策略成功通知", "REDEEM_SUCCESS": "倉位贖回成功通知", "REDEEM_NO_RETURN": "倉位結算(無收益)通知" + }, + "templateTypeDescriptions": { + "ORDER_SUCCESS": "訂單創建成功時發送的通知", + "ORDER_FAILED": "訂單創建失敗時發送的通知", + "ORDER_FILTERED": "訂單被風控過濾時發送的通知", + "CRYPTO_TAIL_SUCCESS": "加密價差策略下單成功時發送的通知", + "REDEEM_SUCCESS": "倉位贖回成功時發送的通知", + "REDEEM_NO_RETURN": "倉位結算但無收益時發送的通知" } }, "telegramConfig": { diff --git a/frontend/src/pages/NotificationSettingsPage.tsx b/frontend/src/pages/NotificationSettingsPage.tsx index 2be6d60..29dfa4b 100644 --- a/frontend/src/pages/NotificationSettingsPage.tsx +++ b/frontend/src/pages/NotificationSettingsPage.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState, useCallback } from 'react' -import { Card, Table, Button, Space, Tag, Popconfirm, message, Typography, Modal, Form, Input, Switch, Tooltip, Row, Col, Menu } from 'antd' +import { Card, Table, Button, Space, Tag, Popconfirm, message, Typography, Modal, Form, Input, Switch, Tooltip, Row, Col, Tabs } from 'antd' import { PlusOutlined, EditOutlined, DeleteOutlined, SendOutlined, CopyOutlined, ReloadOutlined, CheckOutlined, RobotOutlined, FormOutlined } from '@ant-design/icons' import { useTranslation } from 'react-i18next' import { apiService } from '../services/api' @@ -10,28 +10,27 @@ import TextArea from 'antd/es/input/TextArea' const { Title, Text, Paragraph } = Typography -const templateTypeMenuStyle: React.CSSProperties = { - border: 'none', - background: 'transparent', -} - -const variableChipStyle: React.CSSProperties = { - display: 'inline-block', +const variableTagStyle: React.CSSProperties = { + display: 'inline-flex', + alignItems: 'center', cursor: 'pointer', - marginBottom: 8, - marginRight: 8, - borderRadius: 16, - padding: '6px 12px', - fontSize: 13, - transition: 'all 0.2s', - border: '1px solid #d9d9d9', - background: '#fafafa', + marginBottom: 6, + marginRight: 6, + borderRadius: 6, + padding: '4px 10px', + fontSize: 12, + transition: 'all 0.2s ease', + border: '1px solid #e8e8e8', + background: '#ffffff', + color: 'rgba(0, 0, 0, 0.65)', } -const variableChipHoverStyle: React.CSSProperties = { +const variableTagHoverStyle: React.CSSProperties = { borderColor: '#1890ff', background: '#e6f7ff', color: '#1890ff', + transform: 'translateY(-1px)', + boxShadow: '0 2px 4px rgba(24, 144, 255, 0.2)', } /** @@ -61,12 +60,10 @@ const NotificationSettingsPage: React.FC = () => { // 模板配置相关状态 const [templateTypes, setTemplateTypes] = useState([]) - const [templates, setTemplates] = useState([]) const [selectedTemplateType, setSelectedTemplateType] = useState('ORDER_SUCCESS') const [currentTemplate, setCurrentTemplate] = useState(null) const [templateVariables, setTemplateVariables] = useState(null) const [templateContent, setTemplateContent] = useState('') - const [templateLoading, setTemplateLoading] = useState(false) const [testTemplateLoading, setTestTemplateLoading] = useState(false) // 加载机器人配置 @@ -79,11 +76,6 @@ const NotificationSettingsPage: React.FC = () => { fetchTemplateTypes() }, []) - // 加载模板数据 - useEffect(() => { - fetchTemplates() - }, []) - // 当选中的模板类型改变时,加载模板详情和变量 useEffect(() => { if (selectedTemplateType) { @@ -119,20 +111,6 @@ const NotificationSettingsPage: React.FC = () => { } } - const fetchTemplates = async () => { - setTemplateLoading(true) - try { - const response = await apiService.notifications.getTemplates() - if (response.data.code === 0 && response.data.data) { - setTemplates(response.data.data) - } - } catch (error) { - console.error('获取模板列表失败:', error) - } finally { - setTemplateLoading(false) - } - } - const fetchTemplateDetail = async (templateType: string) => { try { const response = await apiService.notifications.getTemplateDetail({ templateType }) @@ -332,7 +310,6 @@ const NotificationSettingsPage: React.FC = () => { }) if (response.data.code === 0) { message.success(t('notificationSettings.templates.saveSuccess')) - fetchTemplates() fetchTemplateDetail(selectedTemplateType) } else { message.error(response.data.msg || t('notificationSettings.templates.saveFailed')) @@ -349,7 +326,6 @@ const NotificationSettingsPage: React.FC = () => { }) if (response.data.code === 0) { message.success(t('notificationSettings.templates.resetSuccess')) - fetchTemplates() fetchTemplateDetail(selectedTemplateType) } else { message.error(response.data.msg || t('notificationSettings.templates.resetFailed')) @@ -387,19 +363,21 @@ const NotificationSettingsPage: React.FC = () => { const renderVariableItem = (variable: TemplateVariable) => { const isHover = variableHoverKey === variable.key + const label = t(`notificationSettings.templates.variableLabels.${variable.key}`) + const description = t(`notificationSettings.templates.variableDescriptions.${variable.key}`) return ( - + handleCopyVariable(variable.key)} onMouseEnter={() => setVariableHoverKey(variable.key)} onMouseLeave={() => setVariableHoverKey(null)} onKeyDown={(e) => e.key === 'Enter' && handleCopyVariable(variable.key)} > - - {variable.label} + + {label} ) @@ -412,20 +390,20 @@ const NotificationSettingsPage: React.FC = () => { + {t('notificationSettings.templates.variables')} } style={{ height: '100%', borderRadius: 8 }} - bodyStyle={{ paddingTop: 12 }} + bodyStyle={{ padding: '12px 16px', maxHeight: 420, overflowY: 'auto' }} > {templateVariables.categories.map(category => { const categoryVariables = templateVariables.variables.filter(v => v.category === category.key) if (categoryVariables.length === 0) return null return ( -
- - {t(CATEGORY_LABELS[category.key] || category.label)} +
+ + {t(CATEGORY_LABELS[category.key])}
{categoryVariables.sort((a, b) => a.sortOrder - b.sortOrder).map(renderVariableItem)} @@ -433,7 +411,7 @@ const NotificationSettingsPage: React.FC = () => {
) })} - + {t('notificationSettings.templates.clickToCopy')} @@ -544,14 +522,12 @@ const NotificationSettingsPage: React.FC = () => { } ] - const templateTypeMenuItems = templateTypes.map(type => ({ + const templateTypeTabItems = templateTypes.map(type => ({ key: type.type, - icon: , label: ( -
-
{t(`notificationSettings.templateTypes.${type.type}`)}
-
{type.description}
-
+ + {t(`notificationSettings.templateTypes.${type.type}`)} + ), })) @@ -594,31 +570,26 @@ const NotificationSettingsPage: React.FC = () => { {t('notificationSettings.templateConfig')} } - loading={templateLoading} style={{ marginBottom: '16px' }} > - - -
- - {t('notificationSettings.templates.templateType')} - - handleTemplateTypeChange(key)} - /> -
- - - + + + + +
- {t('notificationSettings.templates.templateContent')} + {t('notificationSettings.templates.templateContent')} {currentTemplate && ( - + {currentTemplate.isDefault ? t('notificationSettings.templates.isDefault') : t('notificationSettings.templates.isCustom')} )} @@ -630,14 +601,14 @@ const NotificationSettingsPage: React.FC = () => { okText={t('common.confirm')} cancelText={t('common.cancel')} > - - - @@ -646,11 +617,12 @@ const NotificationSettingsPage: React.FC = () => {