File size: 7,525 Bytes
291850b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339fff1
291850b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
import React, { useState, useMemo } from 'react';
import { ChevronDown, ChevronUp, Download, FileSpreadsheet, TrendingUp, TrendingDown } from 'lucide-react';
import { KLinePoint } from '../types';

interface KLineTextTableProps {
  data: KLinePoint[];
  birthYear?: number;
  className?: string;
}

const KLineTextTable: React.FC<KLineTextTableProps> = ({
  data,
  birthYear,
  className = '',
}) => {
  const [expanded, setExpanded] = useState(false);
  const currentYear = new Date().getFullYear();

  // Calculate display range - default show 10 years around current age
  const displayData = useMemo(() => {
    if (!data || data.length === 0) return [];

    if (expanded) {
      return data;
    }

    // Find current year index
    const currentYearIndex = data.findIndex(d => d.year === currentYear);

    if (currentYearIndex === -1) {
      // If current year not found, show first 10 items
      return data.slice(0, 10);
    }

    // Show 5 years before and 5 years after current year
    const startIndex = Math.max(0, currentYearIndex - 5);
    const endIndex = Math.min(data.length, currentYearIndex + 5);

    return data.slice(startIndex, endIndex);
  }, [data, expanded, currentYear]);

  // Export to Excel (CSV format)
  const handleExportExcel = () => {
    if (!data || data.length === 0) return;

    // Create CSV content with BOM for Excel compatibility
    const BOM = '\uFEFF';
    const headers = ['年龄', '年份', '干支', '大运', '评分', '趋势', '运势分析'];
    const rows = data.map(item => {
      const trend = item.close >= item.open ? '上涨' : '下跌';
      // Escape quotes and handle line breaks in reason
      const reason = (item.reason || '').replace(/"/g, '""').replace(/\n/g, ' ');
      return [
        `${item.age}岁`,
        item.year,
        item.ganZhi || '',
        item.daYun || '',
        item.score,
        trend,
        `"${reason}"`,
      ].join(',');
    });

    const csvContent = BOM + headers.join(',') + '\n' + rows.join('\n');
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = `比迹_流年详批_${new Date().getTime()}.csv`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  };

  if (!data || data.length === 0) {
    return null;
  }

  return (
    <div className={`bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden ${className}`}>
      {/* Header */}
      <div className="px-6 py-4 border-b border-gray-100 flex items-center justify-between bg-gradient-to-r from-gray-50 to-white">
        <div className="flex items-center gap-2">
          <div className="w-1 h-6 bg-indigo-600 rounded-full"></div>
          <h3 className="text-lg font-bold text-gray-800 font-serif-sc">流年运势详批</h3>
          <span className="text-sm text-gray-500">
            ({expanded ? `全部 ${data.length} 年` : `近10年`})
          </span>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={handleExportExcel}
            className="flex items-center gap-1.5 px-3 py-1.5 text-sm text-emerald-600 bg-emerald-50 hover:bg-emerald-100 rounded-lg transition-colors"
          >
            <FileSpreadsheet className="w-4 h-4" />
            导出Excel
          </button>
        </div>
      </div>

      {/* Table */}
      <div className="overflow-x-auto">
        <table className="w-full text-sm">
          <thead>
            <tr className="bg-gray-50 text-gray-600 font-medium">
              <th className="px-4 py-3 text-center whitespace-nowrap border-r border-gray-100 w-16">年龄</th>
              <th className="px-4 py-3 text-center whitespace-nowrap border-r border-gray-100 w-32">年份/干支</th>
              <th className="px-4 py-3 text-center whitespace-nowrap border-r border-gray-100 w-16">大运</th>
              <th className="px-4 py-3 text-center whitespace-nowrap border-r border-gray-100 w-20">评分</th>
              <th className="px-4 py-3 text-left">运势分析</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-100">
            {displayData.map((item, index) => {
              const isCurrentYear = item.year === currentYear;
              const isUpTrend = item.close >= item.open;
              const scoreColor = isUpTrend ? 'text-green-600' : 'text-red-600';
              const scoreBg = isUpTrend ? 'bg-green-50' : 'bg-red-50';

              return (
                <tr
                  key={item.year}
                  className={`hover:bg-gray-50 transition-colors ${isCurrentYear ? 'bg-amber-50/50' : ''}`}
                >
                  {/* Age */}
                  <td className="px-4 py-3 text-center border-r border-gray-100">
                    <span className="font-mono font-medium text-gray-700">
                      {item.age}<span className="text-gray-400 text-xs"></span>
                    </span>
                  </td>

                  {/* Year + GanZhi */}
                  <td className="px-4 py-3 text-center border-r border-gray-100">
                    <div className="flex flex-col items-center">
                      <span className="font-bold text-gray-800">{item.year}</span>
                      <span className="text-indigo-600 font-medium">{item.ganZhi || '-'}</span>
                    </div>
                  </td>

                  {/* DaYun */}
                  <td className="px-4 py-3 text-center border-r border-gray-100">
                    <span className="text-purple-600 font-medium">{item.daYun || '-'}</span>
                  </td>

                  {/* Score */}
                  <td className="px-4 py-3 text-center border-r border-gray-100">
                    <div className={`inline-flex items-center gap-1 px-2 py-1 rounded-lg ${scoreBg}`}>
                      <span className={`font-bold ${scoreColor}`}>{item.score}</span>
                      {isUpTrend ? (
                        <TrendingUp className={`w-3.5 h-3.5 ${scoreColor}`} />
                      ) : (
                        <TrendingDown className={`w-3.5 h-3.5 ${scoreColor}`} />
                      )}
                    </div>
                  </td>

                  {/* Reason */}
                  <td className="px-4 py-3">
                    <p className="text-gray-700 leading-relaxed text-justify">
                      {item.reason || '暂无详细分析'}
                    </p>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      {/* Expand/Collapse Button */}
      <div className="px-6 py-3 border-t border-gray-100 bg-gray-50">
        <button
          onClick={() => setExpanded(!expanded)}
          className="w-full flex items-center justify-center gap-2 py-2 text-sm font-medium text-indigo-600 hover:text-indigo-700 hover:bg-indigo-50 rounded-lg transition-colors"
        >
          {expanded ? (
            <>
              <ChevronUp className="w-4 h-4" />
              收起,仅显示近10年
            </>
          ) : (
            <>
              <ChevronDown className="w-4 h-4" />
              展开查看全部 {data.length} 年运势
            </>
          )}
        </button>
      </div>
    </div>
  );
};

export default KLineTextTable;