Ethscriptions commited on
Commit
bee3be0
·
verified ·
1 Parent(s): 1fa56f3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -0
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import streamlit as st
3
+ import matplotlib.pyplot as plt
4
+ import matplotlib.font_manager as font_manager
5
+ import io
6
+ import base64
7
+ import os
8
+ from datetime import datetime, timedelta
9
+ import math
10
+ from matplotlib.patches import FancyBboxPatch
11
+ from pypinyin import lazy_pinyin, Style
12
+
13
+ def get_font(size=14):
14
+ font_path = "simHei.ttc"
15
+ if not os.path.exists(font_path):
16
+ font_path = "SimHei.ttf"
17
+ return font_manager.FontProperties(fname=font_path, size=size)
18
+
19
+ def get_pinyin_abbr(text):
20
+ """获取文本前两个汉字的拼音首字母"""
21
+ if not text:
22
+ return ""
23
+ # 提取前两个汉字
24
+ chars = [c for c in text if '\u4e00' <= c <= '\u9fff']
25
+ if len(chars) < 2:
26
+ chars = chars + [''] * (2 - len(chars))
27
+ else:
28
+ chars = chars[:2]
29
+ # 获取拼音首字母
30
+ pinyin_list = lazy_pinyin(chars, style=Style.FIRST_LETTER)
31
+ return ''.join(pinyin_list).upper()
32
+
33
+ def process_schedule(file):
34
+ try:
35
+ date_df = pd.read_excel(file, header=None, skiprows=7, nrows=1, usecols=[3])
36
+ date_str = pd.to_datetime(date_df.iloc[0, 0]).strftime('%Y-%m-%d')
37
+ base_date = pd.to_datetime(date_str).date()
38
+ except:
39
+ date_str = datetime.today().strftime('%Y-%m-%d')
40
+ base_date = datetime.today().date()
41
+
42
+ try:
43
+ df = pd.read_excel(file, header=9, usecols=[1, 2, 4, 5])
44
+ df.columns = ['Hall', 'StartTime', 'EndTime', 'Movie']
45
+ df['Hall'] = df['Hall'].ffill()
46
+ df.dropna(subset=['StartTime', 'EndTime', 'Movie'], inplace=True)
47
+ df['Hall'] = df['Hall'].astype(str).str.extract(r'(\d+号)')
48
+ df['StartTime_dt'] = pd.to_datetime(df['StartTime'], format='%H:%M', errors='coerce').apply(
49
+ lambda t: t.replace(year=base_date.year, month=base_date.month, day=base_date.day) if pd.notnull(t) else t
50
+ )
51
+ df['EndTime_dt'] = pd.to_datetime(df['EndTime'], format='%H:%M', errors='coerce').apply(
52
+ lambda t: t.replace(year=base_date.year, month=base_date.month, day=base_date.day) if pd.notnull(t) else t
53
+ )
54
+ df.loc[df['EndTime_dt'] < df['StartTime_dt'], 'EndTime_dt'] += timedelta(days=1)
55
+ df = df.sort_values(['Hall', 'StartTime_dt'])
56
+
57
+ merged_rows = []
58
+ for hall, group in df.groupby('Hall'):
59
+ group = group.sort_values('StartTime_dt')
60
+ current = None
61
+ for _, row in group.iterrows():
62
+ if current is None:
63
+ current = row.copy()
64
+ else:
65
+ if row['Movie'] == current['Movie']:
66
+ current['EndTime_dt'] = row['EndTime_dt']
67
+ else:
68
+ merged_rows.append(current)
69
+ current = row.copy()
70
+ if current is not None:
71
+ merged_rows.append(current)
72
+
73
+ merged_df = pd.DataFrame(merged_rows)
74
+
75
+ # 将开始时间统一提前10分钟,结束时间统一提前5分钟
76
+ merged_df['StartTime_dt'] = merged_df['StartTime_dt'] - timedelta(minutes=10)
77
+ merged_df['EndTime_dt'] = merged_df['EndTime_dt'] - timedelta(minutes=5)
78
+
79
+ merged_df['StartTime_str'] = merged_df['StartTime_dt'].dt.strftime('%H:%M')
80
+ merged_df['EndTime_str'] = merged_df['EndTime_dt'].dt.strftime('%H:%M')
81
+
82
+ return merged_df[['Hall', 'Movie', 'StartTime_str', 'EndTime_str']], date_str
83
+ except:
84
+ return None, date_str
85
+
86
+ def create_print_layout(data, date_str):
87
+ if data is None or data.empty:
88
+ return None
89
+
90
+ fig = plt.figure(figsize=(8.27, 11.69), dpi=300)
91
+ ax = fig.add_subplot(111)
92
+ ax.set_axis_off()
93
+
94
+ # Pre-load fonts
95
+ date_font = get_font(12)
96
+ movie_font_size = 14
97
+ hall_font_size = movie_font_size * 0.8
98
+ hall_font = get_font(hall_font_size)
99
+ movie_font = get_font(movie_font_size)
100
+
101
+ ax.text(0.00, 1.00, date_str, fontsize=12, color='#A9A9A9',
102
+ ha='left', va='top', fontproperties=date_font, transform=ax.transAxes, zorder=2)
103
+
104
+ halls = sorted(data['Hall'].unique(), key=lambda h: int(h.replace('号','')) if h else 0)
105
+
106
+ total_lines = sum(len(data[data['Hall'] == hall]) for hall in halls) + (len(halls) - 1)
107
+ available_height = 0.98 - 0.05
108
+ line_spacing = available_height / total_lines if total_lines > 0 else 0.04
109
+ # movie_font_size = 14 # Moved up
110
+ # hall_font_size = movie_font_size * 0.8 # Moved up
111
+ y_position = 0.98
112
+
113
+ for hall in halls:
114
+ hall_data = data[data['Hall'] == hall]
115
+ y_block_top = y_position
116
+ hall_num = hall.replace("号", "")
117
+ hall_text = f"${hall_num}^{{\\#}}$"
118
+ movie_count = 1
119
+
120
+ for _, row in hall_data.iterrows():
121
+ ax.text(0.03, y_position, hall_text if movie_count == 1 else "",
122
+ fontsize=hall_font_size, fontweight='bold',
123
+ ha='left', va='top', fontproperties=hall_font,
124
+ transform=ax.transAxes, zorder=2)
125
+
126
+ # 获取电影名前两个字的拼音首字母
127
+ pinyin_abbr = get_pinyin_abbr(row['Movie'])
128
+
129
+ # 电影名称左对齐,限制在0.2到0.6的区域内
130
+ ax.text(0.20, y_position, f"{movie_count}. {pinyin_abbr} {row['Movie']}",
131
+ fontsize=movie_font_size, ha='left', va='top', fontproperties=movie_font,
132
+ transform=ax.transAxes, zorder=2, clip_on=True,
133
+ bbox=dict(boxstyle="square,pad=0.0", fc="none", ec="none", alpha=0))
134
+
135
+ # 时间信息右对齐,固定在0.95位置
136
+ ax.text(0.95, y_position, f"{row['StartTime_str']} - {row['EndTime_str']}",
137
+ fontsize=movie_font_size, ha='right', va='top', fontproperties=movie_font,
138
+ transform=ax.transAxes, zorder=2)
139
+
140
+ y_position -= line_spacing
141
+ movie_count += 1
142
+
143
+ y_block_bottom = y_position
144
+ y_position -= line_spacing
145
+ rect = FancyBboxPatch((0.03, y_block_bottom), 0.94, y_block_top - y_block_bottom,
146
+ boxstyle="round,pad=0.005,rounding_size=0.005",
147
+ edgecolor='gray', facecolor='white',
148
+ linewidth=0.8, zorder=1, transform=ax.transAxes)
149
+ ax.add_patch(rect)
150
+
151
+ buffer = io.BytesIO()
152
+ plt.savefig(buffer, format='png', bbox_inches='tight', pad_inches=0.1)
153
+ buffer.seek(0)
154
+ image_base64 = base64.b64encode(buffer.getvalue()).decode()
155
+ plt.close(fig)
156
+
157
+ return f"data:image/png;base64,{image_base64}"
158
+
159
+ st.set_page_config(page_title="LED 屏幕时间表打印", layout="wide")
160
+ st.title("LED 屏幕时间表打印")
161
+
162
+ uploaded_file = st.file_uploader("选择打开【放映时间核对表.xls】文件", type=["xls", "xlsx"])
163
+
164
+ if uploaded_file:
165
+ with st.spinner("正在处理中,请稍候..."):
166
+ schedule, date_str = process_schedule(uploaded_file)
167
+ if schedule is not None:
168
+ image = create_print_layout(schedule, date_str)
169
+ st.image(image, caption=f"LED 屏幕时间表 {date_str}", use_container_width=True)
170
+ else:
171
+ st.error("无法处理文件,请检查文件格式或内容是否正确。")
172
+
173
+