style(EventFormModal): 升级为黑金主题样式
- 股票选择器下拉菜单适配深色背景 - Tag 标签改为金色边框和背景 - 自选股提示文字颜色优化 - 添加 ConfigProvider 深色主题支持 - Less 样式文件大幅扩展,支持完整黑金风格 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
/* EventFormModal.less - 投资计划/复盘弹窗响应式样式 */
|
/* EventFormModal.less - 投资计划/复盘弹窗黑金主题样式 */
|
||||||
|
|
||||||
// ==================== 变量定义 ====================
|
// ==================== 变量定义 ====================
|
||||||
@mobile-breakpoint: 768px;
|
@mobile-breakpoint: 768px;
|
||||||
@modal-border-radius-mobile: 12px;
|
@modal-border-radius-mobile: 16px;
|
||||||
@modal-border-radius-desktop: 8px;
|
@modal-border-radius-desktop: 12px;
|
||||||
|
|
||||||
// 间距
|
// 间距
|
||||||
@spacing-xs: 4px;
|
@spacing-xs: 4px;
|
||||||
@@ -18,64 +18,317 @@
|
|||||||
@font-size-sm: 14px;
|
@font-size-sm: 14px;
|
||||||
@font-size-md: 16px;
|
@font-size-md: 16px;
|
||||||
|
|
||||||
// 颜色
|
// 黑金主题色
|
||||||
@color-border: #f0f0f0;
|
@color-bg-deep: #0A0A14;
|
||||||
@color-text-secondary: #999;
|
@color-bg-primary: #0F0F1A;
|
||||||
@color-error: #ff4d4f;
|
@color-bg-elevated: #1A1A2E;
|
||||||
|
@color-bg-surface: #252540;
|
||||||
|
@color-bg-input: rgba(26, 26, 46, 0.8);
|
||||||
|
|
||||||
|
@color-gold-400: #D4AF37;
|
||||||
|
@color-gold-500: #B8960C;
|
||||||
|
@color-gold-gradient: linear-gradient(135deg, #D4AF37 0%, #F5E6A3 100%);
|
||||||
|
|
||||||
|
@color-line-subtle: rgba(212, 175, 55, 0.1);
|
||||||
|
@color-line-default: rgba(212, 175, 55, 0.2);
|
||||||
|
@color-line-emphasis: rgba(212, 175, 55, 0.4);
|
||||||
|
|
||||||
|
@color-text-primary: rgba(255, 255, 255, 0.95);
|
||||||
|
@color-text-secondary: rgba(255, 255, 255, 0.6);
|
||||||
|
@color-text-muted: rgba(255, 255, 255, 0.4);
|
||||||
|
|
||||||
|
@color-error: #EF4444;
|
||||||
|
|
||||||
|
// ==================== 全局 Modal 遮罩层样式 ====================
|
||||||
|
// 使用 rootClassName="event-form-modal-root" 来控制 mask 样式
|
||||||
|
.event-form-modal-root {
|
||||||
|
.ant-modal-mask {
|
||||||
|
background: rgba(0, 0, 0, 0.7) !important;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-wrap {
|
||||||
|
// 确保 wrap 层也有正确的样式
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 主样式 ====================
|
// ==================== 主样式 ====================
|
||||||
.event-form-modal {
|
.event-form-modal {
|
||||||
|
|
||||||
// Modal 整体
|
// Modal 整体
|
||||||
.ant-modal-content {
|
.ant-modal-content {
|
||||||
|
background: linear-gradient(135deg, @color-bg-elevated 0%, @color-bg-primary 100%);
|
||||||
|
border: 1px solid @color-line-default;
|
||||||
border-radius: @modal-border-radius-desktop;
|
border-radius: @modal-border-radius-desktop;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 24px rgba(212, 175, 55, 0.1);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modal 标题放大加粗
|
// Modal 头部
|
||||||
|
.ant-modal-header {
|
||||||
|
background: transparent;
|
||||||
|
border-bottom: 1px solid @color-line-subtle;
|
||||||
|
padding: @spacing-lg @spacing-xxl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal 标题
|
||||||
.ant-modal-title {
|
.ant-modal-title {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
background: @color-gold-gradient;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭按钮
|
||||||
|
.ant-modal-close {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-gold-400;
|
||||||
|
background: rgba(212, 175, 55, 0.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-modal-body {
|
.ant-modal-body {
|
||||||
padding: @spacing-xxl;
|
padding: @spacing-xxl;
|
||||||
padding-top: 36px; // 增加标题与表单间距
|
padding-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal 底部
|
||||||
|
.ant-modal-footer {
|
||||||
|
background: transparent;
|
||||||
|
border-top: 1px solid @color-line-subtle;
|
||||||
|
padding: @spacing-lg @spacing-xxl;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-form-item {
|
.ant-form-item {
|
||||||
margin-bottom: @spacing-xl;
|
margin-bottom: @spacing-xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单标签加粗,左对齐
|
// 表单标签
|
||||||
.ant-form-item-label {
|
.ant-form-item-label {
|
||||||
text-align: left !important;
|
text-align: left !important;
|
||||||
|
|
||||||
> label {
|
> label {
|
||||||
font-weight: 600 !important;
|
font-weight: 600 !important;
|
||||||
color: #333;
|
color: @color-text-primary !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入框通用样式(支持 Ant Design v5 的 outlined 类名)
|
||||||
|
.ant-input,
|
||||||
|
.ant-input-outlined,
|
||||||
|
.ant-picker,
|
||||||
|
.ant-picker-outlined,
|
||||||
|
.ant-select-selector,
|
||||||
|
.ant-select-outlined .ant-select-selector {
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
border: 1px solid @color-line-default !important;
|
||||||
|
color: @color-text-primary !important;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @color-line-emphasis !important;
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:focus-within,
|
||||||
|
&.ant-input-focused,
|
||||||
|
&.ant-picker-focused,
|
||||||
|
&.ant-select-focused {
|
||||||
|
border-color: @color-gold-400 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.2) !important;
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: @color-text-muted !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入框 focus 状态增强
|
||||||
|
.ant-input:focus,
|
||||||
|
.ant-input-outlined:focus,
|
||||||
|
.ant-input-affix-wrapper:focus,
|
||||||
|
.ant-input-affix-wrapper-focused {
|
||||||
|
border-color: @color-gold-400 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入框 wrapper
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
border-color: @color-line-default !important;
|
||||||
|
|
||||||
|
.ant-input {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input-suffix {
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入框 placeholder
|
||||||
|
.ant-input::placeholder,
|
||||||
|
.ant-picker-input input::placeholder,
|
||||||
|
.ant-select-selection-placeholder {
|
||||||
|
color: @color-text-muted !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文本域
|
||||||
|
.ant-input-textarea,
|
||||||
|
.ant-input-textarea-show-count {
|
||||||
|
textarea,
|
||||||
|
.ant-input {
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
border: 1px solid @color-line-default !important;
|
||||||
|
color: @color-text-primary !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @color-line-emphasis !important;
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: @color-gold-400 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.2) !important;
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: @color-text-muted !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文本域 outlined 变体
|
||||||
|
.ant-input-textarea-outlined,
|
||||||
|
textarea.ant-input-outlined {
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
border: 1px solid @color-line-default !important;
|
||||||
|
color: @color-text-primary !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @color-line-emphasis !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: @color-gold-400 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.2) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字符计数样式
|
// 字符计数样式
|
||||||
.ant-input-textarea-show-count::after {
|
.ant-input-textarea-show-count::after {
|
||||||
font-size: @font-size-xs;
|
font-size: @font-size-xs;
|
||||||
color: @color-text-secondary;
|
color: @color-text-muted;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 日期选择器全宽
|
// 日期选择器
|
||||||
.ant-picker {
|
.ant-picker {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
.ant-picker-input > input {
|
||||||
|
color: @color-text-primary !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-suffix,
|
||||||
|
.ant-picker-clear {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select 选择器
|
||||||
|
.ant-select {
|
||||||
|
.ant-select-selector {
|
||||||
|
min-height: 38px;
|
||||||
|
background: @color-bg-input !important;
|
||||||
|
border: 1px solid @color-line-default !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-select-focused .ant-select-selector,
|
||||||
|
&:hover .ant-select-selector {
|
||||||
|
border-color: @color-line-emphasis !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-select-focused .ant-select-selector {
|
||||||
|
border-color: @color-gold-400 !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-selection-item {
|
||||||
|
color: @color-text-primary !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-selection-search-input {
|
||||||
|
color: @color-text-primary !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-arrow {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-clear {
|
||||||
|
background: @color-bg-elevated;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-gold-400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select 多选模式下的标签
|
||||||
|
.ant-select-multiple .ant-select-selection-item {
|
||||||
|
background: rgba(212, 175, 55, 0.15) !important;
|
||||||
|
border: 1px solid rgba(212, 175, 55, 0.3) !important;
|
||||||
|
color: @color-gold-400 !important;
|
||||||
|
|
||||||
|
.ant-select-selection-item-remove {
|
||||||
|
color: @color-gold-400;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 股票标签样式
|
// 股票标签样式
|
||||||
.ant-tag {
|
.ant-tag {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
border-radius: @spacing-xs;
|
border-radius: @spacing-xs;
|
||||||
|
background: rgba(212, 175, 55, 0.15) !important;
|
||||||
|
border: 1px solid rgba(212, 175, 55, 0.3) !important;
|
||||||
|
color: @color-gold-400 !important;
|
||||||
|
|
||||||
|
.ant-tag-close-icon {
|
||||||
|
color: @color-gold-400;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模板按钮组
|
// 模板按钮组
|
||||||
.template-buttons {
|
.template-buttons {
|
||||||
.ant-btn {
|
.ant-btn {
|
||||||
font-size: @font-size-xs;
|
font-size: @font-size-xs;
|
||||||
|
background: rgba(212, 175, 55, 0.1);
|
||||||
|
border: 1px solid @color-line-default;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(212, 175, 55, 0.2);
|
||||||
|
border-color: @color-line-emphasis;
|
||||||
|
color: @color-gold-400;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +336,32 @@
|
|||||||
.modal-footer {
|
.modal-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.ant-btn-primary {
|
||||||
|
background: linear-gradient(135deg, @color-gold-400 0%, @color-gold-500 100%);
|
||||||
|
border: none;
|
||||||
|
color: @color-bg-deep;
|
||||||
|
font-weight: 600;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, lighten(@color-gold-400, 5%) 0%, lighten(@color-gold-500, 5%) 100%);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(212, 175, 55, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: rgba(212, 175, 55, 0.3);
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -90,14 +369,114 @@
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 错误状态动画
|
// 错误状态
|
||||||
.ant-form-item-has-error {
|
.ant-form-item-has-error {
|
||||||
.ant-input,
|
.ant-input,
|
||||||
.ant-picker,
|
.ant-picker,
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
|
border-color: @color-error !important;
|
||||||
animation: shake 0.3s ease-in-out;
|
animation: shake 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-form-item-explain-error {
|
||||||
|
color: @color-error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select 下拉菜单(挂载在 body 上,需要全局样式)
|
||||||
|
.ant-select-dropdown {
|
||||||
|
background: @color-bg-elevated !important;
|
||||||
|
border: 1px solid @color-line-default;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
.ant-select-item {
|
||||||
|
color: @color-text-primary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(212, 175, 55, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-select-item-option-selected {
|
||||||
|
background: rgba(212, 175, 55, 0.2);
|
||||||
|
color: @color-gold-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-select-item-option-active {
|
||||||
|
background: rgba(212, 175, 55, 0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-item-empty {
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分割线
|
||||||
|
.ant-divider {
|
||||||
|
border-color: @color-line-subtle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提示文字
|
||||||
|
span[style*="color: #999"] {
|
||||||
|
color: @color-text-muted !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期选择器下拉面板
|
||||||
|
.ant-picker-dropdown {
|
||||||
|
.ant-picker-panel-container {
|
||||||
|
background: @color-bg-elevated;
|
||||||
|
border: 1px solid @color-line-default;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-header {
|
||||||
|
color: @color-text-primary;
|
||||||
|
border-bottom: 1px solid @color-line-subtle;
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-gold-400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-content th {
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-cell {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
|
||||||
|
&:hover .ant-picker-cell-inner {
|
||||||
|
background: rgba(212, 175, 55, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-picker-cell-in-view {
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-picker-cell-selected .ant-picker-cell-inner {
|
||||||
|
background: @color-gold-400;
|
||||||
|
color: @color-bg-deep;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-picker-cell-today .ant-picker-cell-inner::before {
|
||||||
|
border-color: @color-gold-400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-footer {
|
||||||
|
border-top: 1px solid @color-line-subtle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-today-btn {
|
||||||
|
color: @color-gold-400;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 移动端适配 ====================
|
// ==================== 移动端适配 ====================
|
||||||
@@ -142,7 +521,6 @@
|
|||||||
.ant-modal-footer {
|
.ant-modal-footer {
|
||||||
padding: @spacing-md @spacing-lg;
|
padding: @spacing-md @spacing-lg;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border-top: 1px solid @color-border;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单项间距
|
// 表单项间距
|
||||||
@@ -182,10 +560,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 底部按钮
|
// 底部按钮
|
||||||
.ant-modal-footer .ant-btn {
|
.modal-footer .ant-btn-primary {
|
||||||
font-size: @font-size-md;
|
font-size: @font-size-md;
|
||||||
height: 40px;
|
height: 44px;
|
||||||
border-radius: @spacing-sm;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import {
|
|||||||
message,
|
message,
|
||||||
Space,
|
Space,
|
||||||
Spin,
|
Spin,
|
||||||
|
ConfigProvider,
|
||||||
|
theme,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import type { SelectProps } from 'antd';
|
import type { SelectProps } from 'antd';
|
||||||
import {
|
import {
|
||||||
@@ -393,7 +395,7 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
// 判断是否显示自选股列表
|
// 判断是否显示自选股列表
|
||||||
const isShowingWatchlist = !searchText && stockOptions === watchlistOptions;
|
const isShowingWatchlist = !searchText && stockOptions === watchlistOptions;
|
||||||
|
|
||||||
// 股票选择器选项配置
|
// 股票选择器选项配置(黑金主题)
|
||||||
const selectProps: SelectProps<string[]> = {
|
const selectProps: SelectProps<string[]> = {
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
placeholder: allStocksLoading ? '加载股票列表中...' : '输入股票代码或名称搜索',
|
placeholder: allStocksLoading ? '加载股票列表中...' : '输入股票代码或名称搜索',
|
||||||
@@ -401,12 +403,15 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
onSearch: handleStockSearch,
|
onSearch: handleStockSearch,
|
||||||
loading: watchlistLoading || allStocksLoading,
|
loading: watchlistLoading || allStocksLoading,
|
||||||
notFoundContent: allStocksLoading ? (
|
notFoundContent: allStocksLoading ? (
|
||||||
<div style={{ textAlign: 'center', padding: '8px' }}>
|
<div style={{ textAlign: 'center', padding: '8px', color: 'rgba(255,255,255,0.6)' }}>
|
||||||
<Spin size="small" />
|
<Spin size="small" />
|
||||||
<span style={{ marginLeft: 8 }}>加载中...</span>
|
<span style={{ marginLeft: 8 }}>加载中...</span>
|
||||||
</div>
|
</div>
|
||||||
) : '暂无结果',
|
) : <span style={{ color: 'rgba(255,255,255,0.4)' }}>暂无结果</span>,
|
||||||
options: stockOptions,
|
options: stockOptions,
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
onFocus: () => {
|
onFocus: () => {
|
||||||
if (stockOptions.length === 0) {
|
if (stockOptions.length === 0) {
|
||||||
setStockOptions(watchlistOptions);
|
setStockOptions(watchlistOptions);
|
||||||
@@ -416,41 +421,49 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
const { label: tagLabel, closable, onClose: onTagClose } = props;
|
const { label: tagLabel, closable, onClose: onTagClose } = props;
|
||||||
return (
|
return (
|
||||||
<Tag
|
<Tag
|
||||||
color="blue"
|
|
||||||
closable={closable}
|
closable={closable}
|
||||||
onClose={onTagClose}
|
onClose={onTagClose}
|
||||||
style={{ marginRight: 3 }}
|
style={{
|
||||||
|
marginRight: 3,
|
||||||
|
background: 'rgba(212, 175, 55, 0.15)',
|
||||||
|
border: '1px solid rgba(212, 175, 55, 0.3)',
|
||||||
|
color: '#D4AF37',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{tagLabel}
|
{tagLabel}
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
popupRender: (menu) => (
|
popupRender: (menu) => (
|
||||||
<>
|
<div style={{
|
||||||
|
background: '#1A1A2E',
|
||||||
|
border: '1px solid rgba(212, 175, 55, 0.2)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
}}>
|
||||||
{isShowingWatchlist && watchlistOptions.length > 0 && (
|
{isShowingWatchlist && watchlistOptions.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div style={{ padding: '4px 8px 0' }}>
|
<div style={{ padding: '8px 12px 4px' }}>
|
||||||
<span style={{ fontSize: 12, color: '#999' }}>
|
<span style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)' }}>
|
||||||
<StarOutlined style={{ marginRight: 4, color: '#faad14' }} />
|
<StarOutlined style={{ marginRight: 4, color: '#D4AF37' }} />
|
||||||
我的自选股
|
我的自选股
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Divider style={{ margin: '4px 0 0' }} />
|
<Divider style={{ margin: '4px 0 0', borderColor: 'rgba(212, 175, 55, 0.1)' }} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{menu}
|
{menu}
|
||||||
{!isShowingWatchlist && searchText && (
|
{!isShowingWatchlist && searchText && (
|
||||||
<>
|
<>
|
||||||
<Divider style={{ margin: '8px 0' }} />
|
<Divider style={{ margin: '8px 0', borderColor: 'rgba(212, 175, 55, 0.1)' }} />
|
||||||
<div style={{ padding: '0 8px 4px' }}>
|
<div style={{ padding: '0 12px 8px' }}>
|
||||||
<span style={{ fontSize: 12, color: '#999' }}>
|
<span style={{ fontSize: 12, color: 'rgba(255,255,255,0.4)' }}>
|
||||||
<BulbOutlined style={{ marginRight: 4 }} />
|
<BulbOutlined style={{ marginRight: 4 }} />
|
||||||
搜索结果(输入代码或名称)
|
搜索结果(输入代码或名称)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -462,9 +475,47 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
return eventType === 'plan' ? '创建计划' : '创建复盘';
|
return eventType === 'plan' ? '创建计划' : '创建复盘';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 黑金主题样式
|
||||||
|
const modalStyles = {
|
||||||
|
mask: {
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
background: 'linear-gradient(135deg, #1A1A2E 0%, #0F0F1A 100%)',
|
||||||
|
border: '1px solid rgba(212, 175, 55, 0.2)',
|
||||||
|
borderRadius: '12px',
|
||||||
|
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.5), 0 0 24px rgba(212, 175, 55, 0.1)',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
background: 'transparent',
|
||||||
|
borderBottom: '1px solid rgba(212, 175, 55, 0.1)',
|
||||||
|
padding: '16px 24px',
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
padding: '24px',
|
||||||
|
paddingTop: '24px',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
background: 'transparent',
|
||||||
|
borderTop: '1px solid rgba(212, 175, 55, 0.1)',
|
||||||
|
padding: '16px 24px',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={`${mode === 'edit' ? '编辑' : '新建'}${eventType === 'plan' ? '投资计划' : '复盘'}`}
|
title={
|
||||||
|
<span style={{
|
||||||
|
fontSize: '20px',
|
||||||
|
fontWeight: 700,
|
||||||
|
background: 'linear-gradient(135deg, #D4AF37 0%, #F5E6A3 100%)',
|
||||||
|
WebkitBackgroundClip: 'text',
|
||||||
|
WebkitTextFillColor: 'transparent',
|
||||||
|
}}>
|
||||||
|
{`${mode === 'edit' ? '编辑' : '新建'}${eventType === 'plan' ? '投资计划' : '复盘'}`}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
open={isOpen}
|
open={isOpen}
|
||||||
onCancel={onClose}
|
onCancel={onClose}
|
||||||
width={600}
|
width={600}
|
||||||
@@ -472,25 +523,71 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
maskClosable={true}
|
maskClosable={true}
|
||||||
keyboard
|
keyboard
|
||||||
className="event-form-modal"
|
className="event-form-modal"
|
||||||
|
styles={modalStyles}
|
||||||
|
closeIcon={
|
||||||
|
<span style={{ color: 'rgba(255,255,255,0.6)', fontSize: '16px' }}>✕</span>
|
||||||
|
}
|
||||||
footer={
|
footer={
|
||||||
<div className="modal-footer">
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
loading={saving}
|
loading={saving}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, #D4AF37 0%, #B8960C 100%)',
|
||||||
|
border: 'none',
|
||||||
|
color: '#0A0A14',
|
||||||
|
fontWeight: 600,
|
||||||
|
height: '40px',
|
||||||
|
padding: '0 24px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{getButtonText()}
|
{getButtonText()}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div ref={modalContentRef}>
|
<ConfigProvider
|
||||||
{isOpen && <Form
|
theme={{
|
||||||
form={form}
|
algorithm: theme.darkAlgorithm,
|
||||||
layout="horizontal"
|
token: {
|
||||||
labelCol={{ span: 4 }}
|
colorPrimary: '#D4AF37',
|
||||||
wrapperCol={{ span: 20 }}
|
colorBgContainer: 'rgba(26, 26, 46, 0.8)',
|
||||||
|
colorBorder: 'rgba(212, 175, 55, 0.2)',
|
||||||
|
colorBorderSecondary: 'rgba(212, 175, 55, 0.1)',
|
||||||
|
colorText: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
colorTextSecondary: 'rgba(255, 255, 255, 0.6)',
|
||||||
|
colorTextPlaceholder: 'rgba(255, 255, 255, 0.4)',
|
||||||
|
colorBgElevated: '#1A1A2E',
|
||||||
|
colorFillSecondary: 'rgba(212, 175, 55, 0.1)',
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Input: {
|
||||||
|
activeBorderColor: '#D4AF37',
|
||||||
|
hoverBorderColor: 'rgba(212, 175, 55, 0.4)',
|
||||||
|
activeShadow: '0 0 0 2px rgba(212, 175, 55, 0.2)',
|
||||||
|
},
|
||||||
|
Select: {
|
||||||
|
optionActiveBg: 'rgba(212, 175, 55, 0.1)',
|
||||||
|
optionSelectedBg: 'rgba(212, 175, 55, 0.2)',
|
||||||
|
optionSelectedColor: '#D4AF37',
|
||||||
|
},
|
||||||
|
DatePicker: {
|
||||||
|
activeBorderColor: '#D4AF37',
|
||||||
|
hoverBorderColor: 'rgba(212, 175, 55, 0.4)',
|
||||||
|
activeShadow: '0 0 0 2px rgba(212, 175, 55, 0.2)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div ref={modalContentRef}>
|
||||||
|
{isOpen && <Form
|
||||||
|
form={form}
|
||||||
|
layout="horizontal"
|
||||||
|
labelCol={{ span: 4 }}
|
||||||
|
wrapperCol={{ span: 20 }}
|
||||||
labelAlign="left"
|
labelAlign="left"
|
||||||
requiredMark={false}
|
requiredMark={false}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
@@ -501,7 +598,7 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
{/* 标题 */}
|
{/* 标题 */}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="title"
|
name="title"
|
||||||
label={<span style={{ fontWeight: 600 }}>标题 <span style={{ color: '#ff4d4f' }}>*</span></span>}
|
label={<span style={{ fontWeight: 600, color: 'rgba(255,255,255,0.95)' }}>标题 <span style={{ color: '#D4AF37' }}>*</span></span>}
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: '请输入标题' },
|
{ required: true, message: '请输入标题' },
|
||||||
{ max: 50, message: '标题不能超过50个字符' },
|
{ max: 50, message: '标题不能超过50个字符' },
|
||||||
@@ -511,17 +608,31 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
placeholder={getTitlePlaceholder()}
|
placeholder={getTitlePlaceholder()}
|
||||||
maxLength={50}
|
maxLength={50}
|
||||||
showCount
|
showCount
|
||||||
|
styles={{
|
||||||
|
input: {
|
||||||
|
background: 'rgba(26, 26, 46, 0.8)',
|
||||||
|
borderColor: 'rgba(212, 175, 55, 0.2)',
|
||||||
|
color: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
color: 'rgba(255, 255, 255, 0.4)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{/* 日期 */}
|
{/* 日期 */}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="date"
|
name="date"
|
||||||
label={<span style={{ fontWeight: 600 }}>{eventType === 'plan' ? '计划日期' : '复盘日期'} <span style={{ color: '#ff4d4f' }}>*</span></span>}
|
label={<span style={{ fontWeight: 600, color: 'rgba(255,255,255,0.95)' }}>{eventType === 'plan' ? '计划日期' : '复盘日期'} <span style={{ color: '#D4AF37' }}>*</span></span>}
|
||||||
rules={[{ required: true, message: '请选择日期' }]}
|
rules={[{ required: true, message: '请选择日期' }]}
|
||||||
>
|
>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
style={{ width: '100%' }}
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
background: 'rgba(26, 26, 46, 0.8)',
|
||||||
|
borderColor: 'rgba(212, 175, 55, 0.2)',
|
||||||
|
}}
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
placeholder="选择日期"
|
placeholder="选择日期"
|
||||||
allowClear={false}
|
allowClear={false}
|
||||||
@@ -531,7 +642,7 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
{/* 描述/内容 - 上下布局 */}
|
{/* 描述/内容 - 上下布局 */}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="content"
|
name="content"
|
||||||
label={<span style={{ fontWeight: 600 }}>{eventType === 'plan' ? '计划详情' : '复盘内容'} <span style={{ color: '#ff4d4f' }}>*</span></span>}
|
label={<span style={{ fontWeight: 600, color: 'rgba(255,255,255,0.95)' }}>{eventType === 'plan' ? '计划详情' : '复盘内容'} <span style={{ color: '#D4AF37' }}>*</span></span>}
|
||||||
rules={[{ required: true, message: '请输入内容' }]}
|
rules={[{ required: true, message: '请输入内容' }]}
|
||||||
labelCol={{ span: 24 }}
|
labelCol={{ span: 24 }}
|
||||||
wrapperCol={{ span: 24 }}
|
wrapperCol={{ span: 24 }}
|
||||||
@@ -542,18 +653,28 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
rows={8}
|
rows={8}
|
||||||
showCount
|
showCount
|
||||||
maxLength={2000}
|
maxLength={2000}
|
||||||
style={{ resize: 'vertical' }}
|
style={{
|
||||||
|
resize: 'vertical',
|
||||||
|
background: 'rgba(26, 26, 46, 0.8)',
|
||||||
|
borderColor: 'rgba(212, 175, 55, 0.2)',
|
||||||
|
color: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{/* 模板快捷按钮 - 独立放置在 Form.Item 外部 */}
|
{/* 模板快捷按钮 - 独立放置在 Form.Item 外部 */}
|
||||||
<div style={{ marginBottom: 24 }}>
|
<div style={{ marginBottom: 24 }}>
|
||||||
<Space wrap size="small" className="template-buttons">
|
<Space wrap size="small">
|
||||||
{templates.map((template) => (
|
{templates.map((template) => (
|
||||||
<Button
|
<Button
|
||||||
key={template.label}
|
key={template.label}
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => handleInsertTemplate(template)}
|
onClick={() => handleInsertTemplate(template)}
|
||||||
|
style={{
|
||||||
|
background: 'rgba(212, 175, 55, 0.1)',
|
||||||
|
borderColor: 'rgba(212, 175, 55, 0.2)',
|
||||||
|
color: 'rgba(255, 255, 255, 0.6)',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{template.label}
|
{template.label}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -564,12 +685,13 @@ export const EventFormModal: React.FC<EventFormModalProps> = ({
|
|||||||
{/* 关联股票 */}
|
{/* 关联股票 */}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="stocks"
|
name="stocks"
|
||||||
label={<span style={{ fontWeight: 600 }}>关联股票</span>}
|
label={<span style={{ fontWeight: 600, color: 'rgba(255,255,255,0.95)' }}>关联股票</span>}
|
||||||
>
|
>
|
||||||
<Select {...selectProps} />
|
<Select {...selectProps} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>}
|
</Form>}
|
||||||
</div>
|
</div>
|
||||||
|
</ConfigProvider>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user