Ethscriptions commited on
Commit
ab2f00e
·
verified ·
1 Parent(s): 7c643bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -4
app.py CHANGED
@@ -57,8 +57,8 @@ def format_seq(n):
57
  if not isinstance(n, int) or n <= 0:
58
  return str(n)
59
  circled_chars = "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳" \
60
- "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟" \
61
- "㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿"
62
  if 1 <= n <= 50:
63
  return circled_chars[n - 1]
64
  return f'({n})'
@@ -117,13 +117,19 @@ def create_print_layout_led(data, date_str):
117
  A4_width_in, A4_height_in = 8.27, 11.69
118
  dpi = 300
119
  total_content_rows = len(data)
120
- totalA = total_content_rows + 2
 
 
 
 
 
121
  row_height = A4_height_in / totalA
122
  data = data.reset_index(drop=True)
123
  data['hall_str'] = '$' + data['Hall'].str.replace('号', '') + '^{\#}$'
124
  data['seq_str'] = data['Seq'].apply(format_seq)
125
  data['pinyin_abbr'] = data['Movie'].apply(get_pinyin_abbr)
126
  data['time_str'] = data['StartTime_str'] + ' - ' + data['EndTime_str']
 
127
  temp_fig = plt.figure(figsize=(A4_width_in, A4_height_in), dpi=dpi)
128
  renderer = temp_fig.canvas.get_renderer()
129
  base_font_size_pt = (row_height * 0.9) * 72
@@ -143,8 +149,9 @@ def create_print_layout_led(data, date_str):
143
  pinyin_col_width = get_col_width_in(data['pinyin_abbr'], base_font_size_pt)
144
  time_col_width = get_col_width_in(data['time_str'], base_font_size_pt)
145
  movie_col_width = A4_width_in - (
146
- margin_col_width * 2 + hall_col_width + seq_col_width + pinyin_col_width + time_col_width)
147
  plt.close(temp_fig)
 
148
  col_widths = {'hall': hall_col_width, 'seq': seq_col_width, 'movie': movie_col_width, 'pinyin': pinyin_col_width,
149
  'time': time_col_width}
150
  col_x_starts = {}
@@ -159,29 +166,36 @@ def create_print_layout_led(data, date_str):
159
  x_line = col_x_starts[col_name] + col_widths[col_name]
160
  line_top_y, line_bottom_y = A4_height_in - row_height, row_height
161
  ax.add_line(Line2D([x_line, x_line], [line_bottom_y, line_top_y], color='gray', linestyle=':', linewidth=0.5))
 
162
  last_hall_drawn = None
163
  for i, row in data.iterrows():
164
  y_bottom = A4_height_in - (i + 2) * row_height
165
  y_center = y_bottom + row_height / 2
 
166
  if row['Hall'] != last_hall_drawn:
167
  ax.text(col_x_starts['hall'] + col_widths['hall'] / 2, y_center, row['hall_str'],
168
  fontproperties=get_font_regular(base_font_size_pt), ha='center', va='center')
169
  last_hall_drawn = row['Hall']
 
170
  ax.text(col_x_starts['seq'] + col_widths['seq'] / 2, y_center, row['seq_str'],
171
  fontproperties=get_font_regular(seq_font_size_pt), ha='center', va='center')
172
  ax.text(col_x_starts['pinyin'] + col_widths['pinyin'] / 2, y_center, row['pinyin_abbr'],
173
  fontproperties=get_font_regular(base_font_size_pt), ha='center', va='center')
174
  ax.text(col_x_starts['time'] + col_widths['time'] / 2, y_center, row['time_str'],
175
  fontproperties=get_font_regular(base_font_size_pt), ha='center', va='center')
 
176
  movie_font_size = base_font_size_pt
177
  movie_font_prop = get_font_regular(movie_font_size)
178
  text_w_px, _, _ = renderer.get_text_width_height_descent(row['Movie'], movie_font_prop, ismath=False)
179
  text_w_in = text_w_px / dpi
180
  max_width_in = col_widths['movie'] * 0.9
 
181
  if text_w_in > max_width_in:
182
  movie_font_size *= (max_width_in / text_w_in)
183
  movie_font_prop = get_font_regular(movie_font_size)
 
184
  ax.text(col_x_starts['movie'] + 0.05, y_center, row['Movie'], fontproperties=movie_font_prop, ha='left', va='center')
 
185
  is_last_in_hall = (i == len(data) - 1) or (row['Hall'] != data.loc[i + 1, 'Hall'])
186
  line_start_x = margin_col_width
187
  line_end_x = A4_width_in - margin_col_width
@@ -199,7 +213,9 @@ def create_print_layout_led(data, date_str):
199
  ax.set_ylim(0, A4_height_in)
200
  ax.text(margin_col_width, A4_height_in - (row_height / 2), date_str,
201
  fontproperties=get_font_regular(10), color='#A9A9A9', ha='left', va='center')
 
202
  draw_figure(fig, ax)
 
203
  buf = io.BytesIO()
204
  fig.savefig(buf, format=format_type, dpi=dpi, bbox_inches='tight', pad_inches=0)
205
  buf.seek(0)
@@ -207,6 +223,7 @@ def create_print_layout_led(data, date_str):
207
  mime_type = 'image/png' if format_type == 'png' else 'application/pdf'
208
  outputs[format_type] = f"data:{mime_type};base64,{data_uri}"
209
  plt.close(fig)
 
210
  return outputs
211
 
212
  # --- '放映场次核对表' 处理函数 ---
@@ -221,28 +238,36 @@ def process_schedule_times(file):
221
  base_date = datetime.today().date()
222
  df['StartTime'] = pd.to_datetime(df['StartTime'])
223
  df['EndTime'] = pd.to_datetime(df['EndTime'])
 
224
  business_start = datetime.strptime(f"{base_date} {BUSINESS_START}", "%Y-%m-%d %H:%M")
225
  business_end = datetime.strptime(f"{base_date} {BUSINESS_END}", "%Y-%m-%d %H:%M")
226
  if business_end < business_start:
227
  business_end += timedelta(days=1)
 
228
  for idx, row in df.iterrows():
229
  end_time = row['EndTime']
230
  if end_time.hour < 9:
231
  df.at[idx, 'EndTime'] = end_time + timedelta(days=1)
232
  if row['StartTime'].hour >= 21 and end_time.hour < 9:
233
  df.at[idx, 'EndTime'] = end_time + timedelta(days=1)
 
234
  df['time_for_comparison'] = df['EndTime'].apply(lambda x: datetime.combine(base_date, x.time()))
235
  df.loc[df['time_for_comparison'].dt.hour < 9, 'time_for_comparison'] += timedelta(days=1)
 
236
  valid_times = (((df['time_for_comparison'] >= datetime.combine(base_date, business_start.time())) &
237
  (df['time_for_comparison'] <= datetime.combine(base_date + timedelta(days=1), business_end.time()))))
238
  df = df[valid_times]
 
239
  df = df.sort_values('EndTime')
240
  split_time = datetime.strptime(f"{base_date} {SPLIT_TIME}", "%Y-%m-%d %H:%M")
241
  split_time_for_comparison = df['time_for_comparison'].apply(lambda x: datetime.combine(base_date, split_time.time()))
 
242
  part1 = df[df['time_for_comparison'] <= split_time_for_comparison].copy()
243
  part2 = df[df['time_for_comparison'] > split_time_for_comparison].copy()
 
244
  for part in [part1, part2]:
245
  part['EndTime'] = part['EndTime'].dt.strftime('%-H:%M')
 
246
  date_df = pd.read_excel(file, skiprows=5, nrows=1, usecols=[2], header=None)
247
  date_cell = date_df.iloc[0, 0]
248
  try:
@@ -252,6 +277,7 @@ def process_schedule_times(file):
252
  date_str = pd.to_datetime(date_cell).strftime('%Y-%m-%d')
253
  except:
254
  date_str = datetime.today().strftime('%Y-%m-%d')
 
255
  return part1[['Hall', 'EndTime']], part2[['Hall', 'EndTime']], date_str
256
  except Exception as e:
257
  st.error(f"处理文件出错: {str(e)}")
@@ -275,6 +301,7 @@ def create_print_layout_times(data, title, date_str):
275
  fontsize_from_width = target_text_width_pt / (8 * 0.6)
276
  fontsize_from_height = cell_height_pt * 0.8
277
  base_fontsize = min(fontsize_from_width, fontsize_from_height)
 
278
  fig = plt.figure(figsize=(A5_WIDTH_IN, A5_HEIGHT_IN), dpi=300)
279
  fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
280
 
@@ -283,9 +310,11 @@ def create_print_layout_times(data, title, date_str):
283
  hspace=0, wspace=0,
284
  height_ratios=[date_header_height_in] + [cell_height_in] * num_rows,
285
  figure=fig)
 
286
  data_values = data.values.tolist()
287
  while len(data_values) % NUM_COLS != 0:
288
  data_values.append(['', ''])
 
289
  rows_per_col_layout = math.ceil(len(data_values) / NUM_COLS)
290
  sorted_data = [['', '']] * len(data_values)
291
  for i, item in enumerate(data_values):
@@ -295,6 +324,7 @@ def create_print_layout_times(data, title, date_str):
295
  new_index = row_in_col * NUM_COLS + col_idx
296
  if new_index < len(sorted_data):
297
  sorted_data[new_index] = item
 
298
  for idx, (hall, end_time) in enumerate(sorted_data):
299
  if hall and end_time:
300
  row_grid = idx // NUM_COLS + 1
@@ -305,6 +335,7 @@ def create_print_layout_times(data, title, date_str):
305
  spine.set_linestyle((0, (1, 2)))
306
  spine.set_color(BORDER_COLOR)
307
  spine.set_linewidth(0.75)
 
308
  display_text = f"{hall}{end_time}"
309
  ax.text(0.5, 0.5, display_text,
310
  fontproperties=get_font_bold(base_fontsize), # 使用 Bold 字体
@@ -313,6 +344,7 @@ def create_print_layout_times(data, title, date_str):
313
  ax.set_xticks([])
314
  ax.set_yticks([])
315
  ax.set_facecolor('none')
 
316
  ax_date = fig.add_subplot(gs[0, :])
317
  ax_date.text(0.01, 0.5, f"{date_str} {title}",
318
  fontproperties=get_font_bold(base_fontsize * 0.5), # 使用 Bold 字体
@@ -321,6 +353,7 @@ def create_print_layout_times(data, title, date_str):
321
  transform=ax_date.transAxes)
322
  ax_date.set_axis_off()
323
  ax_date.set_facecolor('none')
 
324
  return fig
325
 
326
  fig_for_output = generate_figure()
@@ -328,11 +361,13 @@ def create_print_layout_times(data, title, date_str):
328
  fig_for_output.savefig(png_buffer, format='png')
329
  png_buffer.seek(0)
330
  png_base64 = base64.b64encode(png_buffer.getvalue()).decode()
 
331
  pdf_buffer = io.BytesIO()
332
  with PdfPages(pdf_buffer) as pdf:
333
  pdf.savefig(fig_for_output)
334
  pdf_buffer.seek(0)
335
  pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode()
 
336
  plt.close(fig_for_output)
337
  return {'png': f'data:image/png;base64,{png_base64}', 'pdf': f'data:application/pdf;base64,{pdf_base64}'}
338
 
@@ -362,12 +397,14 @@ if uploaded_file:
362
  st.image(output['png'], use_container_width=True)
363
  else:
364
  st.error("无法处理文件。请检查文件内容和格式是否正确。")
 
365
  elif "场次" in uploaded_file.name:
366
  st.header("散场时间快捷打印")
367
  part1, part2, date_str = process_schedule_times(uploaded_file)
368
  if part1 is not None and part2 is not None:
369
  part1_output = create_print_layout_times(part1, "A", date_str)
370
  part2_output = create_print_layout_times(part2, "C", date_str)
 
371
  col1, col2 = st.columns(2)
372
  with col1:
373
  st.subheader("白班 (散场时间 ≤ 17:00)")
@@ -379,6 +416,7 @@ if uploaded_file:
379
  st.image(part1_output['png'])
380
  else:
381
  st.info("白班没有排期数据。")
 
382
  with col2:
383
  st.subheader("晚班 (散场时间 > 17:00)")
384
  if part2_output:
 
57
  if not isinstance(n, int) or n <= 0:
58
  return str(n)
59
  circled_chars = "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳" \
60
+ "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟" \
61
+ "㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿"
62
  if 1 <= n <= 50:
63
  return circled_chars[n - 1]
64
  return f'({n})'
 
117
  A4_width_in, A4_height_in = 8.27, 11.69
118
  dpi = 300
119
  total_content_rows = len(data)
120
+
121
+ # --- 已修改部分:如果数据条数小于25条,则按25条计算行高以防止字体过大 ---
122
+ layout_rows = max(total_content_rows, 25)
123
+ totalA = layout_rows + 2
124
+ # --- 修改结束 ---
125
+
126
  row_height = A4_height_in / totalA
127
  data = data.reset_index(drop=True)
128
  data['hall_str'] = '$' + data['Hall'].str.replace('号', '') + '^{\#}$'
129
  data['seq_str'] = data['Seq'].apply(format_seq)
130
  data['pinyin_abbr'] = data['Movie'].apply(get_pinyin_abbr)
131
  data['time_str'] = data['StartTime_str'] + ' - ' + data['EndTime_str']
132
+
133
  temp_fig = plt.figure(figsize=(A4_width_in, A4_height_in), dpi=dpi)
134
  renderer = temp_fig.canvas.get_renderer()
135
  base_font_size_pt = (row_height * 0.9) * 72
 
149
  pinyin_col_width = get_col_width_in(data['pinyin_abbr'], base_font_size_pt)
150
  time_col_width = get_col_width_in(data['time_str'], base_font_size_pt)
151
  movie_col_width = A4_width_in - (
152
+ margin_col_width * 2 + hall_col_width + seq_col_width + pinyin_col_width + time_col_width)
153
  plt.close(temp_fig)
154
+
155
  col_widths = {'hall': hall_col_width, 'seq': seq_col_width, 'movie': movie_col_width, 'pinyin': pinyin_col_width,
156
  'time': time_col_width}
157
  col_x_starts = {}
 
166
  x_line = col_x_starts[col_name] + col_widths[col_name]
167
  line_top_y, line_bottom_y = A4_height_in - row_height, row_height
168
  ax.add_line(Line2D([x_line, x_line], [line_bottom_y, line_top_y], color='gray', linestyle=':', linewidth=0.5))
169
+
170
  last_hall_drawn = None
171
  for i, row in data.iterrows():
172
  y_bottom = A4_height_in - (i + 2) * row_height
173
  y_center = y_bottom + row_height / 2
174
+
175
  if row['Hall'] != last_hall_drawn:
176
  ax.text(col_x_starts['hall'] + col_widths['hall'] / 2, y_center, row['hall_str'],
177
  fontproperties=get_font_regular(base_font_size_pt), ha='center', va='center')
178
  last_hall_drawn = row['Hall']
179
+
180
  ax.text(col_x_starts['seq'] + col_widths['seq'] / 2, y_center, row['seq_str'],
181
  fontproperties=get_font_regular(seq_font_size_pt), ha='center', va='center')
182
  ax.text(col_x_starts['pinyin'] + col_widths['pinyin'] / 2, y_center, row['pinyin_abbr'],
183
  fontproperties=get_font_regular(base_font_size_pt), ha='center', va='center')
184
  ax.text(col_x_starts['time'] + col_widths['time'] / 2, y_center, row['time_str'],
185
  fontproperties=get_font_regular(base_font_size_pt), ha='center', va='center')
186
+
187
  movie_font_size = base_font_size_pt
188
  movie_font_prop = get_font_regular(movie_font_size)
189
  text_w_px, _, _ = renderer.get_text_width_height_descent(row['Movie'], movie_font_prop, ismath=False)
190
  text_w_in = text_w_px / dpi
191
  max_width_in = col_widths['movie'] * 0.9
192
+
193
  if text_w_in > max_width_in:
194
  movie_font_size *= (max_width_in / text_w_in)
195
  movie_font_prop = get_font_regular(movie_font_size)
196
+
197
  ax.text(col_x_starts['movie'] + 0.05, y_center, row['Movie'], fontproperties=movie_font_prop, ha='left', va='center')
198
+
199
  is_last_in_hall = (i == len(data) - 1) or (row['Hall'] != data.loc[i + 1, 'Hall'])
200
  line_start_x = margin_col_width
201
  line_end_x = A4_width_in - margin_col_width
 
213
  ax.set_ylim(0, A4_height_in)
214
  ax.text(margin_col_width, A4_height_in - (row_height / 2), date_str,
215
  fontproperties=get_font_regular(10), color='#A9A9A9', ha='left', va='center')
216
+
217
  draw_figure(fig, ax)
218
+
219
  buf = io.BytesIO()
220
  fig.savefig(buf, format=format_type, dpi=dpi, bbox_inches='tight', pad_inches=0)
221
  buf.seek(0)
 
223
  mime_type = 'image/png' if format_type == 'png' else 'application/pdf'
224
  outputs[format_type] = f"data:{mime_type};base64,{data_uri}"
225
  plt.close(fig)
226
+
227
  return outputs
228
 
229
  # --- '放映场次核对表' 处理函数 ---
 
238
  base_date = datetime.today().date()
239
  df['StartTime'] = pd.to_datetime(df['StartTime'])
240
  df['EndTime'] = pd.to_datetime(df['EndTime'])
241
+
242
  business_start = datetime.strptime(f"{base_date} {BUSINESS_START}", "%Y-%m-%d %H:%M")
243
  business_end = datetime.strptime(f"{base_date} {BUSINESS_END}", "%Y-%m-%d %H:%M")
244
  if business_end < business_start:
245
  business_end += timedelta(days=1)
246
+
247
  for idx, row in df.iterrows():
248
  end_time = row['EndTime']
249
  if end_time.hour < 9:
250
  df.at[idx, 'EndTime'] = end_time + timedelta(days=1)
251
  if row['StartTime'].hour >= 21 and end_time.hour < 9:
252
  df.at[idx, 'EndTime'] = end_time + timedelta(days=1)
253
+
254
  df['time_for_comparison'] = df['EndTime'].apply(lambda x: datetime.combine(base_date, x.time()))
255
  df.loc[df['time_for_comparison'].dt.hour < 9, 'time_for_comparison'] += timedelta(days=1)
256
+
257
  valid_times = (((df['time_for_comparison'] >= datetime.combine(base_date, business_start.time())) &
258
  (df['time_for_comparison'] <= datetime.combine(base_date + timedelta(days=1), business_end.time()))))
259
  df = df[valid_times]
260
+
261
  df = df.sort_values('EndTime')
262
  split_time = datetime.strptime(f"{base_date} {SPLIT_TIME}", "%Y-%m-%d %H:%M")
263
  split_time_for_comparison = df['time_for_comparison'].apply(lambda x: datetime.combine(base_date, split_time.time()))
264
+
265
  part1 = df[df['time_for_comparison'] <= split_time_for_comparison].copy()
266
  part2 = df[df['time_for_comparison'] > split_time_for_comparison].copy()
267
+
268
  for part in [part1, part2]:
269
  part['EndTime'] = part['EndTime'].dt.strftime('%-H:%M')
270
+
271
  date_df = pd.read_excel(file, skiprows=5, nrows=1, usecols=[2], header=None)
272
  date_cell = date_df.iloc[0, 0]
273
  try:
 
277
  date_str = pd.to_datetime(date_cell).strftime('%Y-%m-%d')
278
  except:
279
  date_str = datetime.today().strftime('%Y-%m-%d')
280
+
281
  return part1[['Hall', 'EndTime']], part2[['Hall', 'EndTime']], date_str
282
  except Exception as e:
283
  st.error(f"处理文件出错: {str(e)}")
 
301
  fontsize_from_width = target_text_width_pt / (8 * 0.6)
302
  fontsize_from_height = cell_height_pt * 0.8
303
  base_fontsize = min(fontsize_from_width, fontsize_from_height)
304
+
305
  fig = plt.figure(figsize=(A5_WIDTH_IN, A5_HEIGHT_IN), dpi=300)
306
  fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
307
 
 
310
  hspace=0, wspace=0,
311
  height_ratios=[date_header_height_in] + [cell_height_in] * num_rows,
312
  figure=fig)
313
+
314
  data_values = data.values.tolist()
315
  while len(data_values) % NUM_COLS != 0:
316
  data_values.append(['', ''])
317
+
318
  rows_per_col_layout = math.ceil(len(data_values) / NUM_COLS)
319
  sorted_data = [['', '']] * len(data_values)
320
  for i, item in enumerate(data_values):
 
324
  new_index = row_in_col * NUM_COLS + col_idx
325
  if new_index < len(sorted_data):
326
  sorted_data[new_index] = item
327
+
328
  for idx, (hall, end_time) in enumerate(sorted_data):
329
  if hall and end_time:
330
  row_grid = idx // NUM_COLS + 1
 
335
  spine.set_linestyle((0, (1, 2)))
336
  spine.set_color(BORDER_COLOR)
337
  spine.set_linewidth(0.75)
338
+
339
  display_text = f"{hall}{end_time}"
340
  ax.text(0.5, 0.5, display_text,
341
  fontproperties=get_font_bold(base_fontsize), # 使用 Bold 字体
 
344
  ax.set_xticks([])
345
  ax.set_yticks([])
346
  ax.set_facecolor('none')
347
+
348
  ax_date = fig.add_subplot(gs[0, :])
349
  ax_date.text(0.01, 0.5, f"{date_str} {title}",
350
  fontproperties=get_font_bold(base_fontsize * 0.5), # 使用 Bold 字体
 
353
  transform=ax_date.transAxes)
354
  ax_date.set_axis_off()
355
  ax_date.set_facecolor('none')
356
+
357
  return fig
358
 
359
  fig_for_output = generate_figure()
 
361
  fig_for_output.savefig(png_buffer, format='png')
362
  png_buffer.seek(0)
363
  png_base64 = base64.b64encode(png_buffer.getvalue()).decode()
364
+
365
  pdf_buffer = io.BytesIO()
366
  with PdfPages(pdf_buffer) as pdf:
367
  pdf.savefig(fig_for_output)
368
  pdf_buffer.seek(0)
369
  pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode()
370
+
371
  plt.close(fig_for_output)
372
  return {'png': f'data:image/png;base64,{png_base64}', 'pdf': f'data:application/pdf;base64,{pdf_base64}'}
373
 
 
397
  st.image(output['png'], use_container_width=True)
398
  else:
399
  st.error("无法处理文件。请检查文件内容和格式是否正确。")
400
+
401
  elif "场次" in uploaded_file.name:
402
  st.header("散场时间快捷打印")
403
  part1, part2, date_str = process_schedule_times(uploaded_file)
404
  if part1 is not None and part2 is not None:
405
  part1_output = create_print_layout_times(part1, "A", date_str)
406
  part2_output = create_print_layout_times(part2, "C", date_str)
407
+
408
  col1, col2 = st.columns(2)
409
  with col1:
410
  st.subheader("白班 (散场时间 ≤ 17:00)")
 
416
  st.image(part1_output['png'])
417
  else:
418
  st.info("白班没有排期数据。")
419
+
420
  with col2:
421
  st.subheader("晚班 (散场时间 > 17:00)")
422
  if part2_output: