Ethscriptions commited on
Commit
1878cfc
·
verified ·
1 Parent(s): 0c961e6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +189 -188
app.py CHANGED
@@ -12,187 +12,187 @@ from pypinyin import lazy_pinyin, Style
12
  from matplotlib.backends.backend_pdf import PdfPages
13
 
14
  def get_font(size=14):
15
-     font_path = "simHei.ttc"
16
-     if not os.path.exists(font_path):
17
-         font_path = "SimHei.ttf"
18
-     return font_manager.FontProperties(fname=font_path, size=size)
19
 
20
  def get_pinyin_abbr(text):
21
-     """获取文本前两个汉字的拼音首字母"""
22
-     if not text:
23
-         return ""
24
-     # 提取前两个汉字
25
-     chars = [c for c in text if '\u4e00' <= c <= '\u9fff']
26
-     if len(chars) < 2:
27
-         chars = chars + [''] * (2 - len(chars))
28
-     else:
29
-         chars = chars[:2]
30
-     # 获取拼音首字母
31
-     pinyin_list = lazy_pinyin(chars, style=Style.FIRST_LETTER)
32
-     return ''.join(pinyin_list).upper()
33
 
34
  def process_schedule(file):
35
-     try:
36
-         date_df = pd.read_excel(file, header=None, skiprows=7, nrows=1, usecols=[3])
37
-         date_str = pd.to_datetime(date_df.iloc[0, 0]).strftime('%Y-%m-%d')
38
-         base_date = pd.to_datetime(date_str).date()
39
-     except:
40
-         date_str = datetime.today().strftime('%Y-%m-%d')
41
-         base_date = datetime.today().date()
42
-     
43
-     try:
44
-         df = pd.read_excel(file, header=9, usecols=[1, 2, 4, 5])
45
-         df.columns = ['Hall', 'StartTime', 'EndTime', 'Movie']
46
-         df['Hall'] = df['Hall'].ffill()
47
-         df.dropna(subset=['StartTime', 'EndTime', 'Movie'], inplace=True)
48
-         df['Hall'] = df['Hall'].astype(str).str.extract(r'(\d+号)')
49
-         df['StartTime_dt'] = pd.to_datetime(df['StartTime'], format='%H:%M', errors='coerce').apply(
50
-             lambda t: t.replace(year=base_date.year, month=base_date.month, day=base_date.day) if pd.notnull(t) else t
51
-         )
52
-         df['EndTime_dt'] = pd.to_datetime(df['EndTime'], format='%H:%M', errors='coerce').apply(
53
-             lambda t: t.replace(year=base_date.year, month=base_date.month, day=base_date.day) if pd.notnull(t) else t
54
-         )
55
-         df.loc[df['EndTime_dt'] < df['StartTime_dt'], 'EndTime_dt'] += timedelta(days=1)
56
-         df = df.sort_values(['Hall', 'StartTime_dt'])
57
-         
58
-         merged_rows = []
59
-         for hall, group in df.groupby('Hall'):
60
-             group = group.sort_values('StartTime_dt')
61
-             current = None
62
-             for _, row in group.iterrows():
63
-                 if current is None:
64
-                     current = row.copy()
65
-                 else:
66
-                     if row['Movie'] == current['Movie']:
67
-                         current['EndTime_dt'] = row['EndTime_dt']
68
-                     else:
69
-                         merged_rows.append(current)
70
-                         current = row.copy()
71
-             if current is not None:
72
-                 merged_rows.append(current)
73
-         
74
-         merged_df = pd.DataFrame(merged_rows)
75
-         
76
-         # 将开始时间统一提前10分钟,结束时间统一提前5分钟
77
-         merged_df['StartTime_dt'] = merged_df['StartTime_dt'] - timedelta(minutes=10)
78
-         merged_df['EndTime_dt'] = merged_df['EndTime_dt'] - timedelta(minutes=5)
79
-         
80
-         merged_df['StartTime_str'] = merged_df['StartTime_dt'].dt.strftime('%H:%M')
81
-         merged_df['EndTime_str'] = merged_df['EndTime_dt'].dt.strftime('%H:%M')
82
-         
83
-         return merged_df[['Hall', 'Movie', 'StartTime_str', 'EndTime_str']], date_str
84
-     except:
85
-         return None, date_str
86
 
87
  def create_print_layout(data, date_str):
88
-     if data is None or data.empty:
89
-         return None
90
-     
91
-     # 创建PNG图像 - 使用A4纸张大小并最大化内容
92
-     png_fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
93
-     png_ax = png_fig.add_subplot(111)
94
-     png_ax.set_axis_off()
95
-     # 为PNG设置更小的边距以最大化内容
96
-     png_fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02)
97
-     
98
-     # 创建PDF图像 - 使用A4纸张大小
99
-     pdf_fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
100
-     pdf_ax = pdf_fig.add_subplot(111)
101
-     pdf_ax.set_axis_off()
102
-     # 为PDF设置更小的边距
103
-     pdf_fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02)
104
-     
105
-     # 处理两个图形的共同函数
106
-     def process_figure(fig, ax, is_pdf=False):
107
-         # Pre-load fonts
108
-         date_font = get_font(12)
109
-         # 使用更大的字体以最大化利用纸张空间
110
-         font_size_multiplier = 1.2
111
-         movie_font_size = 14 * font_size_multiplier
112
-         hall_font_size = movie_font_size * 0.8
113
-         hall_font = get_font(hall_font_size)
114
-         movie_font = get_font(movie_font_size)
115
-         
116
-         ax.text(0.00, 1.00, date_str, fontsize=12 * font_size_multiplier, color='#A9A9A9',
117
-                 ha='left', va='top', fontproperties=date_font, transform=ax.transAxes, zorder=2)
118
-         
119
-         halls = sorted(data['Hall'].unique(), key=lambda h: int(h.replace('号','')) if h else 0)
120
-         
121
-         total_lines = sum(len(data[data['Hall'] == hall]) for hall in halls) + (len(halls) - 1)
122
-         available_height = 0.98 - 0.02  # 增加可用高度
123
-         line_spacing = available_height / total_lines if total_lines > 0 else 0.04
124
-         y_position = 0.98
125
-         
126
-         for hall in halls:
127
-             hall_data = data[data['Hall'] == hall]
128
-             y_block_top = y_position
129
-             hall_num = hall.replace("号", "")
130
-             hall_text = f"${hall_num}^{{\\#}}$"
131
-             movie_count = 1
132
-             
133
-             for _, row in hall_data.iterrows():
134
-                 ax.text(0.03, y_position, hall_text if movie_count == 1 else "",
135
-                         fontsize=hall_font_size, fontweight='bold',
136
-                         ha='left', va='top', fontproperties=hall_font,
137
-                         transform=ax.transAxes, zorder=2)
138
-                 
139
-                 # 获取电影名前两个字的拼音首字母
140
-                 pinyin_abbr = get_pinyin_abbr(row['Movie'])
141
-                 
142
-                 # 电影名称左对齐,限制在0.2到0.6的区域内
143
-                 ax.text(0.20, y_position, f"{movie_count}. {pinyin_abbr} {row['Movie']}",
144
-                         fontsize=movie_font_size, ha='left', va='top', fontproperties=movie_font,
145
-                         transform=ax.transAxes, zorder=2, clip_on=True,
146
-                         bbox=dict(boxstyle="square,pad=0.0", fc="none", ec="none", alpha=0))
147
-                 
148
-                 # 时间信息右对齐,固定在0.95位置
149
-                 ax.text(0.95, y_position, f"{row['StartTime_str']} - {row['EndTime_str']}",
150
-                         fontsize=movie_font_size, ha='right', va='top', fontproperties=movie_font,
151
-                         transform=ax.transAxes, zorder=2)
152
-                 
153
-                 y_position -= line_spacing
154
-                 movie_count += 1
155
-             
156
-             y_block_bottom = y_position
157
-             y_position -= line_spacing
158
-             rect = FancyBboxPatch((0.03, y_block_bottom), 0.94, y_block_top - y_block_bottom,
159
-                                 boxstyle="round,pad=0.005,rounding_size=0.005",
160
-                                 edgecolor='gray', facecolor='white',
161
-                                 linewidth=0.8, zorder=1, transform=ax.transAxes)
162
-             ax.add_patch(rect)
163
-     
164
-     # 处理PNG图形
165
-     process_figure(png_fig, png_ax)
166
-     
167
-     # 处理PDF图形
168
-     process_figure(pdf_fig, pdf_ax, is_pdf=True)
169
-     
170
-     # 保存PNG图像 - 使用最小边距以最大化内容
171
-     png_buffer = io.BytesIO()
172
-     png_fig.savefig(png_buffer, format='png', bbox_inches='tight', pad_inches=0.05)
173
-     png_buffer.seek(0)
174
-     image_base64 = base64.b64encode(png_buffer.getvalue()).decode()
175
-     plt.close(png_fig)
176
-     
177
-     # 保存PDF文件 - 使用最小边距
178
-     pdf_buffer = io.BytesIO()
179
-     with PdfPages(pdf_buffer) as pdf:
180
-         pdf.savefig(pdf_fig, bbox_inches='tight', pad_inches=0.05)
181
-     pdf_buffer.seek(0)
182
-     pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode()
183
-     plt.close(pdf_fig)
184
-     
185
-     return {
186
-         'png': f"data:image/png;base64,{image_base64}",
187
-         'pdf': f"data:application/pdf;base64,{pdf_base64}"
188
-     }
189
 
190
  def display_pdf(base64_pdf):
191
-     # 在Streamlit中显示PDF
192
-     pdf_display = f"""
193
-     <iframe src="{base64_pdf}" width="100%" height="800" type="application/pdf"></iframe>
194
-     """
195
-     return pdf_display
196
 
197
  st.set_page_config(page_title="LED 屏幕时间表打印", layout="wide")
198
  st.title("LED 屏幕时间表打印")
@@ -200,18 +200,19 @@ st.title("LED 屏幕时间表打印")
200
  uploaded_file = st.file_uploader("选择打开【放映时间核对表.xls】文件", accept_multiple_files=False, type=["xls"])
201
 
202
  if uploaded_file:
203
-     with st.spinner("文件正在处理中,请稍候..."):
204
-         schedule, date_str = process_schedule(uploaded_file)
205
-         if schedule is not None:
206
-             output = create_print_layout(schedule, date_str)
207
-             
208
-             # 创建选项卡以切换PNG和PDF视图
209
-             tab1, tab2 = st.tabs(["PDF 预览", "PNG 预览"])
210
-             
211
-             with tab1:
212
-                 st.markdown(display_pdf(output['pdf']), unsafe_allow_html=True)
213
-             
214
-             with tab2:
215
-                 st.image(output['png'], use_container_width=True)
216
-         else:
217
-             st.error("无法处理文件,请检查文件格式或内容是否正确。")
 
 
12
  from matplotlib.backends.backend_pdf import PdfPages
13
 
14
  def get_font(size=14):
15
+ font_path = "simHei.ttc"
16
+ if not os.path.exists(font_path):
17
+ font_path = "SimHei.ttf"
18
+ return font_manager.FontProperties(fname=font_path, size=size)
19
 
20
  def get_pinyin_abbr(text):
21
+ """获取文本前两个汉字的拼音首字母"""
22
+ if not text:
23
+ return ""
24
+ # 提取前两个汉字
25
+ chars = [c for c in text if '\u4e00' <= c <= '\u9fff']
26
+ if len(chars) < 2:
27
+ chars = chars + [''] * (2 - len(chars))
28
+ else:
29
+ chars = chars[:2]
30
+ # 获取拼音首字母
31
+ pinyin_list = lazy_pinyin(chars, style=Style.FIRST_LETTER)
32
+ return ''.join(pinyin_list).upper()
33
 
34
  def process_schedule(file):
35
+ try:
36
+ date_df = pd.read_excel(file, header=None, skiprows=7, nrows=1, usecols=[3])
37
+ date_str = pd.to_datetime(date_df.iloc[0, 0]).strftime('%Y-%m-%d')
38
+ base_date = pd.to_datetime(date_str).date()
39
+ except:
40
+ date_str = datetime.today().strftime('%Y-%m-%d')
41
+ base_date = datetime.today().date()
42
+
43
+ try:
44
+ df = pd.read_excel(file, header=9, usecols=[1, 2, 4, 5])
45
+ df.columns = ['Hall', 'StartTime', 'EndTime', 'Movie']
46
+ df['Hall'] = df['Hall'].ffill()
47
+ df.dropna(subset=['StartTime', 'EndTime', 'Movie'], inplace=True)
48
+ df['Hall'] = df['Hall'].astype(str).str.extract(r'(\d+号)')
49
+ df['StartTime_dt'] = pd.to_datetime(df['StartTime'], format='%H:%M', errors='coerce').apply(
50
+ lambda t: t.replace(year=base_date.year, month=base_date.month, day=base_date.day) if pd.notnull(t) else t
51
+ )
52
+ df['EndTime_dt'] = pd.to_datetime(df['EndTime'], format='%H:%M', errors='coerce').apply(
53
+ lambda t: t.replace(year=base_date.year, month=base_date.month, day=base_date.day) if pd.notnull(t) else t
54
+ )
55
+ df.loc[df['EndTime_dt'] < df['StartTime_dt'], 'EndTime_dt'] += timedelta(days=1)
56
+ df = df.sort_values(['Hall', 'StartTime_dt'])
57
+
58
+ merged_rows = []
59
+ for hall, group in df.groupby('Hall'):
60
+ group = group.sort_values('StartTime_dt')
61
+ current = None
62
+ for _, row in group.iterrows():
63
+ if current is None:
64
+ current = row.copy()
65
+ else:
66
+ if row['Movie'] == current['Movie']:
67
+ current['EndTime_dt'] = row['EndTime_dt']
68
+ else:
69
+ merged_rows.append(current)
70
+ current = row.copy()
71
+ if current is not None:
72
+ merged_rows.append(current)
73
+
74
+ merged_df = pd.DataFrame(merged_rows)
75
+
76
+ # 将开始时间统一提前10分钟,结束时间统一提前5分钟
77
+ merged_df['StartTime_dt'] = merged_df['StartTime_dt'] - timedelta(minutes=10)
78
+ merged_df['EndTime_dt'] = merged_df['EndTime_dt'] - timedelta(minutes=5)
79
+
80
+ merged_df['StartTime_str'] = merged_df['StartTime_dt'].dt.strftime('%H:%M')
81
+ merged_df['EndTime_str'] = merged_df['EndTime_dt'].dt.strftime('%H:%M')
82
+
83
+ return merged_df[['Hall', 'Movie', 'StartTime_str', 'EndTime_str']], date_str
84
+ except:
85
+ return None, date_str
86
 
87
  def create_print_layout(data, date_str):
88
+ if data is None or data.empty:
89
+ return None
90
+
91
+ # 创建PNG图像 - 使用A4纸张大小并最大化内容
92
+ png_fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
93
+ png_ax = png_fig.add_subplot(111)
94
+ png_ax.set_axis_off()
95
+ # 为PNG设置更小的边距以最大化内容
96
+ png_fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02)
97
+
98
+ # 创建PDF图像 - 使用A4纸张大小
99
+ pdf_fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
100
+ pdf_ax = pdf_fig.add_subplot(111)
101
+ pdf_ax.set_axis_off()
102
+ # 为PDF设置更小的边距
103
+ pdf_fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02)
104
+
105
+ # 处理两个图形的共同函数
106
+ def process_figure(fig, ax, is_pdf=False):
107
+ # Pre-load fonts
108
+ date_font = get_font(12)
109
+ # 使用更大的字体以最大化利用纸张空间
110
+ font_size_multiplier = 1.2
111
+ movie_font_size = 14 * font_size_multiplier
112
+ hall_font_size = movie_font_size * 0.8
113
+ hall_font = get_font(hall_font_size)
114
+ movie_font = get_font(movie_font_size)
115
+
116
+ ax.text(0.00, 1.00, date_str, fontsize=12 * font_size_multiplier, color='#A9A9A9',
117
+ ha='left', va='top', fontproperties=date_font, transform=ax.transAxes, zorder=2)
118
+
119
+ halls = sorted(data['Hall'].unique(), key=lambda h: int(h.replace('号','')) if h else 0)
120
+
121
+ total_lines = sum(len(data[data['Hall'] == hall]) for hall in halls) + (len(halls) - 1)
122
+ available_height = 0.98 - 0.02 # 增加可用高度
123
+ line_spacing = available_height / total_lines if total_lines > 0 else 0.04
124
+ y_position = 0.98
125
+
126
+ for hall in halls:
127
+ hall_data = data[data['Hall'] == hall]
128
+ y_block_top = y_position
129
+ hall_num = hall.replace("号", "")
130
+ hall_text = f"${hall_num}^{{\\#}}$"
131
+ movie_count = 1
132
+
133
+ for _, row in hall_data.iterrows():
134
+ ax.text(0.03, y_position, hall_text if movie_count == 1 else "",
135
+ fontsize=hall_font_size, fontweight='bold',
136
+ ha='left', va='top', fontproperties=hall_font,
137
+ transform=ax.transAxes, zorder=2)
138
+
139
+ # 获取电影名前两个字的拼音首字母
140
+ pinyin_abbr = get_pinyin_abbr(row['Movie'])
141
+
142
+ # 电影名称左对齐,限制在0.2到0.6的区域内
143
+ ax.text(0.20, y_position, f"{movie_count}. {pinyin_abbr} {row['Movie']}",
144
+ fontsize=movie_font_size, ha='left', va='top', fontproperties=movie_font,
145
+ transform=ax.transAxes, zorder=2, clip_on=True,
146
+ bbox=dict(boxstyle="square,pad=0.0", fc="none", ec="none", alpha=0))
147
+
148
+ # 时间信息右对齐,固定在0.95位置
149
+ ax.text(0.95, y_position, f"{row['StartTime_str']} - {row['EndTime_str']}",
150
+ fontsize=movie_font_size, ha='right', va='top', fontproperties=movie_font,
151
+ transform=ax.transAxes, zorder=2)
152
+
153
+ y_position -= line_spacing
154
+ movie_count += 1
155
+
156
+ y_block_bottom = y_position
157
+ y_position -= line_spacing
158
+ rect = FancyBboxPatch((0.03, y_block_bottom), 0.94, y_block_top - y_block_bottom,
159
+ boxstyle="round,pad=0.005,rounding_size=0.005",
160
+ edgecolor='gray', facecolor='white',
161
+ linewidth=0.8, zorder=1, transform=ax.transAxes)
162
+ ax.add_patch(rect)
163
+
164
+ # 处理PNG图形
165
+ process_figure(png_fig, png_ax)
166
+
167
+ # 处理PDF图形
168
+ process_figure(pdf_fig, pdf_ax, is_pdf=True)
169
+
170
+ # 保存PNG图像 - 使用最小边距以最大化内容
171
+ png_buffer = io.BytesIO()
172
+ png_fig.savefig(png_buffer, format='png', bbox_inches='tight', pad_inches=0.05)
173
+ png_buffer.seek(0)
174
+ image_base64 = base64.b64encode(png_buffer.getvalue()).decode()
175
+ plt.close(png_fig)
176
+
177
+ # 保存PDF文件 - 使用最小边距
178
+ pdf_buffer = io.BytesIO()
179
+ with PdfPages(pdf_buffer) as pdf:
180
+ pdf.savefig(pdf_fig, bbox_inches='tight', pad_inches=0.05)
181
+ pdf_buffer.seek(0)
182
+ pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode()
183
+ plt.close(pdf_fig)
184
+
185
+ return {
186
+ 'png': f"data:image/png;base64,{image_base64}",
187
+ 'pdf': f"data:application/pdf;base64,{pdf_base64}"
188
+ }
189
 
190
  def display_pdf(base64_pdf):
191
+ # 在Streamlit中显示PDF
192
+ pdf_display = f"""
193
+ <iframe src="{base64_pdf}" width="100%" height="800" type="application/pdf"></iframe>
194
+ """
195
+ return pdf_display
196
 
197
  st.set_page_config(page_title="LED 屏幕时间表打印", layout="wide")
198
  st.title("LED 屏幕时间表打印")
 
200
  uploaded_file = st.file_uploader("选择打开【放映时间核对表.xls】文件", accept_multiple_files=False, type=["xls"])
201
 
202
  if uploaded_file:
203
+ with st.spinner("文件正在处理中,请稍候..."):
204
+ schedule, date_str = process_schedule(uploaded_file)
205
+ if schedule is not None:
206
+ output = create_print_layout(schedule, date_str)
207
+
208
+ # 创建选项卡以切换PNG和PDF视图
209
+ tab1, tab2 = st.tabs(["PDF 预览", "PNG 预览"])
210
+
211
+ with tab1:
212
+ st.markdown(display_pdf(output['pdf']), unsafe_allow_html=True)
213
+
214
+ with tab2:
215
+ st.image(output['png'], use_container_width=True)
216
+ else:
217
+ st.error("无法处理文件,请检查文件格式或内容是否正确。")
218
+