Ethscriptions commited on
Commit
bc2e078
·
verified ·
1 Parent(s): 1fc48ba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -44
app.py CHANGED
@@ -12,26 +12,28 @@ 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')
@@ -73,7 +75,7 @@ def process_schedule(file):
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
 
@@ -85,28 +87,26 @@ def process_schedule(file):
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
@@ -119,7 +119,7 @@ def create_print_layout(data, date_str):
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
 
@@ -127,45 +127,37 @@ def create_print_layout(data, date_str):
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
- # --- Start of added code ---
154
- # Calculate vertical position for the dotted line, centered in the row
155
- line_y = y_position - (line_spacing * 0.4)
156
-
157
- # Dotted line between hall number and movie title
158
- if movie_count == 1:
159
- ax.plot([0.1, 0.18], [line_y, line_y],
160
- linestyle='dotted', color='gray', linewidth=1,
161
- transform=ax.transAxes, zorder=1)
162
-
163
- # Dotted line between movie title and time
164
- ax.plot([0.65, 0.85], [line_y, line_y],
165
- linestyle='dotted', color='gray', linewidth=1,
166
- transform=ax.transAxes, zorder=1)
167
- # --- End of added code ---
168
-
169
  y_position -= line_spacing
170
  movie_count += 1
171
 
@@ -177,20 +169,18 @@ def create_print_layout(data, date_str):
177
  linewidth=0.8, zorder=1, transform=ax.transAxes)
178
  ax.add_patch(rect)
179
 
180
- # 处理PNG图形
181
  process_figure(png_fig, png_ax)
182
-
183
- # 处理PDF图形
184
  process_figure(pdf_fig, pdf_ax, is_pdf=True)
185
 
186
- # 保存PNG图像 - 使用最小边距以最大化内容
187
  png_buffer = io.BytesIO()
188
  png_fig.savefig(png_buffer, format='png', bbox_inches='tight', pad_inches=0.05)
189
  png_buffer.seek(0)
190
  image_base64 = base64.b64encode(png_buffer.getvalue()).decode()
191
  plt.close(png_fig)
192
 
193
- # 保存PDF文件 - 使用最小边距
194
  pdf_buffer = io.BytesIO()
195
  with PdfPages(pdf_buffer) as pdf:
196
  pdf.savefig(pdf_fig, bbox_inches='tight', pad_inches=0.05)
@@ -204,12 +194,13 @@ def create_print_layout(data, date_str):
204
  }
205
 
206
  def display_pdf(base64_pdf):
207
- # Streamlit中显示PDF
208
  pdf_display = f"""
209
  <iframe src="{base64_pdf}" width="100%" height="800" type="application/pdf"></iframe>
210
  """
211
  return pdf_display
212
 
 
213
  st.set_page_config(page_title="LED 屏幕时间表打印", layout="wide")
214
  st.title("LED 屏幕时间表打印")
215
 
@@ -221,7 +212,7 @@ if uploaded_file:
221
  if schedule is not None:
222
  output = create_print_layout(schedule, date_str)
223
 
224
- # 创建选项卡以切换PNG和PDF视图
225
  tab1, tab2 = st.tabs(["PDF 预览", "PNG 预览"])
226
 
227
  with tab1:
 
12
  from matplotlib.backends.backend_pdf import PdfPages
13
 
14
  def get_font(size=14):
15
+ """Fetches the font properties for the SimHei font."""
16
  font_path = "simHei.ttc"
17
  if not os.path.exists(font_path):
18
  font_path = "SimHei.ttf"
19
  return font_manager.FontProperties(fname=font_path, size=size)
20
 
21
  def get_pinyin_abbr(text):
22
+ """Gets the first letter of the Pinyin for the first two Chinese characters of a text."""
23
  if not text:
24
  return ""
25
+ # Extract the first two Chinese characters
26
  chars = [c for c in text if '\u4e00' <= c <= '\u9fff']
27
  if len(chars) < 2:
28
  chars = chars + [''] * (2 - len(chars))
29
  else:
30
  chars = chars[:2]
31
+ # Get the first letter of the Pinyin
32
  pinyin_list = lazy_pinyin(chars, style=Style.FIRST_LETTER)
33
  return ''.join(pinyin_list).upper()
34
 
35
  def process_schedule(file):
36
+ """Processes the uploaded schedule file to extract and format movie showtimes."""
37
  try:
38
  date_df = pd.read_excel(file, header=None, skiprows=7, nrows=1, usecols=[3])
39
  date_str = pd.to_datetime(date_df.iloc[0, 0]).strftime('%Y-%m-%d')
 
75
 
76
  merged_df = pd.DataFrame(merged_rows)
77
 
78
+ # Adjust start time 10 minutes earlier, end time 5 minutes earlier
79
  merged_df['StartTime_dt'] = merged_df['StartTime_dt'] - timedelta(minutes=10)
80
  merged_df['EndTime_dt'] = merged_df['EndTime_dt'] - timedelta(minutes=5)
81
 
 
87
  return None, date_str
88
 
89
  def create_print_layout(data, date_str):
90
+ """Creates the PNG and PDF print layouts for the schedule."""
91
  if data is None or data.empty:
92
  return None
93
 
94
+ # Create PNG image - A4 size, maximized content
95
  png_fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
96
  png_ax = png_fig.add_subplot(111)
97
  png_ax.set_axis_off()
 
98
  png_fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02)
99
 
100
+ # Create PDF image - A4 size
101
  pdf_fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
102
  pdf_ax = pdf_fig.add_subplot(111)
103
  pdf_ax.set_axis_off()
 
104
  pdf_fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02)
105
 
106
+ # Common function to process both figures
107
  def process_figure(fig, ax, is_pdf=False):
108
  # Pre-load fonts
109
  date_font = get_font(12)
 
110
  font_size_multiplier = 1.2
111
  movie_font_size = 14 * font_size_multiplier
112
  hall_font_size = movie_font_size * 0.8
 
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
 
 
127
  hall_data = data[data['Hall'] == hall]
128
  y_block_top = y_position
129
  hall_num = hall.replace("号", "")
130
+ hall_text_template = f"${hall_num}^{{\\#}}$"
131
  movie_count = 1
132
 
133
  for _, row in hall_data.iterrows():
134
+ pinyin_abbr = get_pinyin_abbr(row['Movie'])
135
+ hall_text = hall_text_template if movie_count == 1 else ""
136
+
137
+ # Draw a line of dots underneath the text
138
+ dots = '·' * 300 # A large number of dots
139
+ ax.text(0.03, y_position, dots,
140
+ fontsize=movie_font_size, color='gray',
141
+ ha='left', va='top', fontproperties=movie_font,
142
+ transform=ax.transAxes, zorder=1.5, clip_on=True)
143
+
144
+ # Draw Hall, Movie, and Time text with a white background to create the leader effect
145
+ ax.text(0.03, y_position, hall_text,
146
  fontsize=hall_font_size, fontweight='bold',
147
  ha='left', va='top', fontproperties=hall_font,
148
+ transform=ax.transAxes, zorder=2,
149
+ bbox=dict(boxstyle="square,pad=0.1", fc="white", ec="none"))
 
 
150
 
 
151
  ax.text(0.20, y_position, f"{movie_count}. {pinyin_abbr} {row['Movie']}",
152
  fontsize=movie_font_size, ha='left', va='top', fontproperties=movie_font,
153
  transform=ax.transAxes, zorder=2, clip_on=True,
154
+ bbox=dict(boxstyle="square,pad=0.1", fc="white", ec="none"))
155
 
 
156
  ax.text(0.95, y_position, f"{row['StartTime_str']} - {row['EndTime_str']}",
157
  fontsize=movie_font_size, ha='right', va='top', fontproperties=movie_font,
158
+ transform=ax.transAxes, zorder=2,
159
+ bbox=dict(boxstyle="square,pad=0.1", fc="white", ec="none"))
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  y_position -= line_spacing
162
  movie_count += 1
163
 
 
169
  linewidth=0.8, zorder=1, transform=ax.transAxes)
170
  ax.add_patch(rect)
171
 
172
+ # Process the figures
173
  process_figure(png_fig, png_ax)
 
 
174
  process_figure(pdf_fig, pdf_ax, is_pdf=True)
175
 
176
+ # Save PNG image
177
  png_buffer = io.BytesIO()
178
  png_fig.savefig(png_buffer, format='png', bbox_inches='tight', pad_inches=0.05)
179
  png_buffer.seek(0)
180
  image_base64 = base64.b64encode(png_buffer.getvalue()).decode()
181
  plt.close(png_fig)
182
 
183
+ # Save PDF file
184
  pdf_buffer = io.BytesIO()
185
  with PdfPages(pdf_buffer) as pdf:
186
  pdf.savefig(pdf_fig, bbox_inches='tight', pad_inches=0.05)
 
194
  }
195
 
196
  def display_pdf(base64_pdf):
197
+ """Generates the HTML to display a base64 encoded PDF in Streamlit."""
198
  pdf_display = f"""
199
  <iframe src="{base64_pdf}" width="100%" height="800" type="application/pdf"></iframe>
200
  """
201
  return pdf_display
202
 
203
+ # --- Streamlit App ---
204
  st.set_page_config(page_title="LED 屏幕时间表打印", layout="wide")
205
  st.title("LED 屏幕时间表打印")
206
 
 
212
  if schedule is not None:
213
  output = create_print_layout(schedule, date_str)
214
 
215
+ # Create tabs for PDF and PNG views
216
  tab1, tab2 = st.tabs(["PDF 预览", "PNG 预览"])
217
 
218
  with tab1: