Ethscriptions commited on
Commit
a54c9ae
·
verified ·
1 Parent(s): 4e99405

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -57
app.py CHANGED
@@ -8,61 +8,43 @@ from matplotlib.patches import Rectangle
8
  import matplotlib.gridspec as gridspec
9
  import math
10
 
11
- # 定义全局常量
12
- SPLIT_TIME = "17:30" # 分界线时间
13
- BUSINESS_START = "09:30" # 营业开始时间
14
- BUSINESS_END = "01:30" # 营业结束时间
15
- BORDER_COLOR = '#A9A9A9' # 深灰色边框
16
 
17
  def process_schedule(file):
18
  """处理上传的 Excel 文件,生成排序和分组后的打印内容"""
19
  try:
20
- # 读取 Excel,跳过前 8 行
21
  df = pd.read_excel(file, skiprows=8)
22
-
23
- # 提取所需列 (G9, H9, J9)
24
- df = df.iloc[:, [6, 7, 9]] # G, H, J 列
25
  df.columns = ['Hall', 'StartTime', 'EndTime']
26
-
27
- # 清理数据
28
  df = df.dropna(subset=['Hall', 'StartTime', 'EndTime'])
29
-
30
- # 转换影厅格式为 "#号" 格式
31
  df['Hall'] = df['Hall'].str.extract(r'(\d+)号').astype(str) + '#'
32
-
33
- # 转换时间格式
34
  df['StartTime'] = pd.to_datetime(df['StartTime']).dt.strftime('%H:%M')
35
  df['EndTime'] = pd.to_datetime(df['EndTime']).dt.strftime('%H:%M')
36
 
37
- # 将时间转换为 datetime 对象便于比较
38
  base_date = datetime.today().date()
39
  df['StartTime'] = pd.to_datetime(base_date.strftime('%Y-%m-%d ') + df['StartTime'])
40
  df['EndTime'] = pd.to_datetime(base_date.strftime('%Y-%m-%d ') + df['EndTime'])
41
 
42
- # 处理跨天情况
43
  df.loc[df['EndTime'] < df['StartTime'], 'EndTime'] += timedelta(days=1)
44
 
45
- # 筛选营业时间内的场次
46
  business_start = datetime.strptime(base_date.strftime('%Y-%m-%d ') + BUSINESS_START, '%Y-%m-%d %H:%M')
47
  business_end = datetime.strptime(base_date.strftime('%Y-%m-%d ') + BUSINESS_END, '%Y-%m-%d %H:%M')
48
  if business_end < business_start:
49
  business_end += timedelta(days=1)
50
 
51
- mask = (
52
- (df['StartTime'] >= business_start) |
53
- (df['StartTime'] <= business_end)
54
- )
55
  df = df[mask]
56
 
57
- # 按散场时间排序
58
  df = df.sort_values('EndTime')
59
 
60
- # 分割数据
61
  split_time = datetime.strptime(base_date.strftime('%Y-%m-%d ') + SPLIT_TIME, '%Y-%m-%d %H:%M')
62
  part1 = df[df['EndTime'] <= split_time].copy()
63
  part2 = df[df['EndTime'] > split_time].copy()
64
 
65
- # 格式化时间显示
66
  for part in [part1, part2]:
67
  part['EndTime'] = part['EndTime'].dt.strftime('%-I:%M')
68
 
@@ -77,66 +59,70 @@ def create_print_layout(data, title):
77
  if data.empty:
78
  return None
79
 
80
- # 设置 A5 纸张竖向尺寸(单位:英寸)
81
  fig = plt.figure(figsize=(5.83, 8.27), dpi=300)
82
-
83
- # 减小边距,最大化利用空间
84
  plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.05)
85
 
86
- # 计算行数和列数
 
 
 
 
87
  total_items = len(data)
88
- num_cols = 3 # 固定为3列
89
- num_rows = math.ceil(total_items / num_cols) # 计算需要的行数
90
 
91
- # 创建网格,减小间距
92
  gs = gridspec.GridSpec(num_rows, num_cols, hspace=0.1, wspace=0.1)
93
 
94
- # 设置字体和样式
95
- plt.rcParams['font.family'] = 'sans-serif'
96
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文字体
97
-
98
- # 计算适合的字体大小(考虑到竖向布局和3列)
99
- base_fontsize = min(50, 280 / num_rows) # 调整基础字体大小
100
 
101
- # 重新组织数据为竖向排列
102
- reshaped_data = []
103
  data_values = data.values.tolist()
104
 
105
- # 填充空值确保数据长度是3的倍数
106
  while len(data_values) % 3 != 0:
107
  data_values.append(['', ''])
 
 
 
 
 
 
108
 
109
- # 按竖向顺序重新排列数据
110
- num_rows = len(data_values) // 3
111
- for col in range(3):
112
- for row in range(num_rows):
113
- idx = row + col * num_rows
114
- if idx < len(data_values):
115
- reshaped_data.append(data_values[idx])
 
 
116
 
117
  # 填充数据
118
- for idx, (hall, end_time) in enumerate(reshaped_data):
119
  if hall and end_time: # 只处理非空数据
120
  row = idx // 3
121
  col = idx % 3
122
 
123
- # 创建子图
124
  ax = plt.subplot(gs[row, col])
125
 
126
- # 设置更深的边框颜色
127
  for spine in ax.spines.values():
128
  spine.set_color(BORDER_COLOR)
129
  spine.set_linewidth(0.5)
130
 
131
- # 将影厅和时间紧密连接显示
132
  display_text = f"{hall}{end_time}"
133
  ax.text(0.5, 0.5, display_text,
134
- fontsize=base_fontsize,
135
- fontweight='bold',
136
- ha='center',
137
  va='center')
138
 
139
- # 设置更小的内边距
140
  ax.set_xlim(-0.02, 1.02)
141
  ax.set_ylim(-0.02, 1.02)
142
 
@@ -144,7 +130,7 @@ def create_print_layout(data, title):
144
  ax.set_xticks([])
145
  ax.set_yticks([])
146
 
147
- # 将图表转换为 base64 字符串
148
  buffer = io.BytesIO()
149
  plt.savefig(buffer, format='png', bbox_inches='tight', pad_inches=0.05)
150
  buffer.seek(0)
 
8
  import matplotlib.gridspec as gridspec
9
  import math
10
 
11
+ # [前面的常量定义和 process_schedule 函数保持不变]
12
+ SPLIT_TIME = "17:30"
13
+ BUSINESS_START = "09:30"
14
+ BUSINESS_END = "01:30"
15
+ BORDER_COLOR = '#A9A9A9'
16
 
17
  def process_schedule(file):
18
  """处理上传的 Excel 文件,生成排序和分组后的打印内容"""
19
  try:
 
20
  df = pd.read_excel(file, skiprows=8)
21
+ df = df.iloc[:, [6, 7, 9]]
 
 
22
  df.columns = ['Hall', 'StartTime', 'EndTime']
 
 
23
  df = df.dropna(subset=['Hall', 'StartTime', 'EndTime'])
 
 
24
  df['Hall'] = df['Hall'].str.extract(r'(\d+)号').astype(str) + '#'
 
 
25
  df['StartTime'] = pd.to_datetime(df['StartTime']).dt.strftime('%H:%M')
26
  df['EndTime'] = pd.to_datetime(df['EndTime']).dt.strftime('%H:%M')
27
 
 
28
  base_date = datetime.today().date()
29
  df['StartTime'] = pd.to_datetime(base_date.strftime('%Y-%m-%d ') + df['StartTime'])
30
  df['EndTime'] = pd.to_datetime(base_date.strftime('%Y-%m-%d ') + df['EndTime'])
31
 
 
32
  df.loc[df['EndTime'] < df['StartTime'], 'EndTime'] += timedelta(days=1)
33
 
 
34
  business_start = datetime.strptime(base_date.strftime('%Y-%m-%d ') + BUSINESS_START, '%Y-%m-%d %H:%M')
35
  business_end = datetime.strptime(base_date.strftime('%Y-%m-%d ') + BUSINESS_END, '%Y-%m-%d %H:%M')
36
  if business_end < business_start:
37
  business_end += timedelta(days=1)
38
 
39
+ mask = (df['StartTime'] >= business_start) | (df['StartTime'] <= business_end)
 
 
 
40
  df = df[mask]
41
 
 
42
  df = df.sort_values('EndTime')
43
 
 
44
  split_time = datetime.strptime(base_date.strftime('%Y-%m-%d ') + SPLIT_TIME, '%Y-%m-%d %H:%M')
45
  part1 = df[df['EndTime'] <= split_time].copy()
46
  part2 = df[df['EndTime'] > split_time].copy()
47
 
 
48
  for part in [part1, part2]:
49
  part['EndTime'] = part['EndTime'].dt.strftime('%-I:%M')
50
 
 
59
  if data.empty:
60
  return None
61
 
62
+ # 设置 A5 纸张竖向尺寸
63
  fig = plt.figure(figsize=(5.83, 8.27), dpi=300)
 
 
64
  plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.05)
65
 
66
+ # 设置字体
67
+ plt.rcParams['font.family'] = 'sans-serif'
68
+ plt.rcParams['font.sans-serif'] = ['SimHei']
69
+
70
+ # 计算行数和总数
71
  total_items = len(data)
72
+ num_cols = 3
73
+ num_rows = math.ceil(total_items / num_cols)
74
 
75
+ # 创建网格
76
  gs = gridspec.GridSpec(num_rows, num_cols, hspace=0.1, wspace=0.1)
77
 
78
+ # 计算字体大小
79
+ base_fontsize = min(50, 280 / num_rows)
 
 
 
 
80
 
81
+ # 重要改动:正确的竖向排序逻辑
 
82
  data_values = data.values.tolist()
83
 
84
+ # 确保数据长度是3的倍数
85
  while len(data_values) % 3 != 0:
86
  data_values.append(['', ''])
87
+
88
+ # 计算每列应该包含的行数
89
+ rows_per_col = math.ceil(len(data_values) / 3)
90
+
91
+ # 创建一个新的数据列表,用于存储重新排序后的数据
92
+ sorted_data = [['', '']] * len(data_values)
93
 
94
+ # 正确的竖向排序逻辑
95
+ for i, item in enumerate(data_values):
96
+ if item[0] and item[1]: # 只处理非空数据
97
+ # 计算���的位置
98
+ row = i % rows_per_col
99
+ col = i // rows_per_col
100
+ new_index = row * 3 + col
101
+ if new_index < len(sorted_data):
102
+ sorted_data[new_index] = item
103
 
104
  # 填充数据
105
+ for idx, (hall, end_time) in enumerate(sorted_data):
106
  if hall and end_time: # 只处理非空数据
107
  row = idx // 3
108
  col = idx % 3
109
 
 
110
  ax = plt.subplot(gs[row, col])
111
 
112
+ # 设置边框
113
  for spine in ax.spines.values():
114
  spine.set_color(BORDER_COLOR)
115
  spine.set_linewidth(0.5)
116
 
117
+ # 显示文本
118
  display_text = f"{hall}{end_time}"
119
  ax.text(0.5, 0.5, display_text,
120
+ fontsize=base_fontsize,
121
+ fontweight='bold',
122
+ ha='center',
123
  va='center')
124
 
125
+ # 设置边距
126
  ax.set_xlim(-0.02, 1.02)
127
  ax.set_ylim(-0.02, 1.02)
128
 
 
130
  ax.set_xticks([])
131
  ax.set_yticks([])
132
 
133
+ # 转换为图片
134
  buffer = io.BytesIO()
135
  plt.savefig(buffer, format='png', bbox_inches='tight', pad_inches=0.05)
136
  buffer.seek(0)