Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -23,18 +23,25 @@ A5_HEIGHT_IN = 8.27
|
|
23 |
NUM_COLS = 3
|
24 |
|
25 |
# --- 字体加载与文本处理函数 ---
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
font_path = "SimHei.ttf"
|
31 |
if os.path.exists(font_path):
|
32 |
return font_manager.FontProperties(fname=font_path, size=size)
|
33 |
else:
|
34 |
-
|
35 |
-
st.warning("警告:未找到SimHei字体文件,部分复杂中文(如电影名)可能无法正确显示。请将 simHei.ttc 或 SimHei.ttf 文件放入项目文件夹。")
|
36 |
return font_manager.FontProperties(family='sans-serif', size=size)
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
def get_pinyin_abbr(text):
|
39 |
"""获取中文文本前两个字的拼音首字母"""
|
40 |
if not text:
|
@@ -56,7 +63,7 @@ def format_seq(n):
|
|
56 |
return circled_chars[n - 1]
|
57 |
return f'({n})'
|
58 |
|
59 |
-
# --- '放映时间核对表' 处理函数
|
60 |
def process_schedule_led(file):
|
61 |
"""处理 '放映时间核对表.xls' 文件"""
|
62 |
try:
|
@@ -104,7 +111,7 @@ def process_schedule_led(file):
|
|
104 |
return None, date_str
|
105 |
|
106 |
def create_print_layout_led(data, date_str):
|
107 |
-
"""为 '放映时间核对表' 生成打印布局 (使用
|
108 |
if data is None or data.empty:
|
109 |
return None
|
110 |
A4_width_in, A4_height_in = 8.27, 11.69
|
@@ -124,7 +131,7 @@ def create_print_layout_led(data, date_str):
|
|
124 |
|
125 |
def get_col_width_in(series, font_size_pt, is_math=False):
|
126 |
if series.empty: return 0
|
127 |
-
font_prop =
|
128 |
longest_str_idx = series.astype(str).str.len().idxmax()
|
129 |
max_content = str(series.loc[longest_str_idx])
|
130 |
text_width_px, _, _ = renderer.get_text_width_height_descent(max_content, font_prop, ismath=is_math)
|
@@ -158,22 +165,22 @@ def create_print_layout_led(data, date_str):
|
|
158 |
y_center = y_bottom + row_height / 2
|
159 |
if row['Hall'] != last_hall_drawn:
|
160 |
ax.text(col_x_starts['hall'] + col_widths['hall'] / 2, y_center, row['hall_str'],
|
161 |
-
fontproperties=
|
162 |
last_hall_drawn = row['Hall']
|
163 |
ax.text(col_x_starts['seq'] + col_widths['seq'] / 2, y_center, row['seq_str'],
|
164 |
-
fontproperties=
|
165 |
ax.text(col_x_starts['pinyin'] + col_widths['pinyin'] / 2, y_center, row['pinyin_abbr'],
|
166 |
-
fontproperties=
|
167 |
ax.text(col_x_starts['time'] + col_widths['time'] / 2, y_center, row['time_str'],
|
168 |
-
fontproperties=
|
169 |
movie_font_size = base_font_size_pt
|
170 |
-
movie_font_prop =
|
171 |
text_w_px, _, _ = renderer.get_text_width_height_descent(row['Movie'], movie_font_prop, ismath=False)
|
172 |
text_w_in = text_w_px / dpi
|
173 |
max_width_in = col_widths['movie'] * 0.9
|
174 |
if text_w_in > max_width_in:
|
175 |
movie_font_size *= (max_width_in / text_w_in)
|
176 |
-
movie_font_prop =
|
177 |
ax.text(col_x_starts['movie'] + 0.05, y_center, row['Movie'], fontproperties=movie_font_prop, ha='left', va='center')
|
178 |
is_last_in_hall = (i == len(data) - 1) or (row['Hall'] != data.loc[i + 1, 'Hall'])
|
179 |
line_start_x = margin_col_width
|
@@ -191,7 +198,7 @@ def create_print_layout_led(data, date_str):
|
|
191 |
ax.set_xlim(0, A4_width_in)
|
192 |
ax.set_ylim(0, A4_height_in)
|
193 |
ax.text(margin_col_width, A4_height_in - (row_height / 2), date_str,
|
194 |
-
fontproperties=
|
195 |
draw_figure(fig, ax)
|
196 |
buf = io.BytesIO()
|
197 |
fig.savefig(buf, format=format_type, dpi=dpi, bbox_inches='tight', pad_inches=0)
|
@@ -202,7 +209,7 @@ def create_print_layout_led(data, date_str):
|
|
202 |
plt.close(fig)
|
203 |
return outputs
|
204 |
|
205 |
-
# --- '放映场次核对表' 处理函数
|
206 |
def process_schedule_times(file):
|
207 |
"""处理 '放映场次核对表.xls' 文件"""
|
208 |
try:
|
@@ -210,7 +217,7 @@ def process_schedule_times(file):
|
|
210 |
df = df.iloc[:, [6, 7, 9]]
|
211 |
df.columns = ['Hall', 'StartTime', 'EndTime']
|
212 |
df = df.dropna(subset=['Hall', 'StartTime', 'EndTime'])
|
213 |
-
df['Hall'] = df['Hall'].str.extract(r'(\d
|
214 |
base_date = datetime.today().date()
|
215 |
df['StartTime'] = pd.to_datetime(df['StartTime'])
|
216 |
df['EndTime'] = pd.to_datetime(df['EndTime'])
|
@@ -251,7 +258,7 @@ def process_schedule_times(file):
|
|
251 |
return None, None, None
|
252 |
|
253 |
def create_print_layout_times(data, title, date_str):
|
254 |
-
"""为 '放映场次核对表' 生成打印布局 (
|
255 |
if data.empty:
|
256 |
return None
|
257 |
|
@@ -268,13 +275,9 @@ def create_print_layout_times(data, title, date_str):
|
|
268 |
fontsize_from_width = target_text_width_pt / (8 * 0.6)
|
269 |
fontsize_from_height = cell_height_pt * 0.8
|
270 |
base_fontsize = min(fontsize_from_width, fontsize_from_height)
|
271 |
-
|
272 |
-
# **修改点**: 使用Matplotlib的默认字体设置
|
273 |
-
plt.rcParams['font.sans-serif'] = plt.rcParamsDefault['font.sans-serif']
|
274 |
-
|
275 |
fig = plt.figure(figsize=(A5_WIDTH_IN, A5_HEIGHT_IN), dpi=300)
|
276 |
fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
|
277 |
-
|
278 |
gs = gridspec.GridSpec(
|
279 |
num_rows + 1, NUM_COLS,
|
280 |
hspace=0, wspace=0,
|
@@ -303,22 +306,17 @@ def create_print_layout_times(data, title, date_str):
|
|
303 |
spine.set_color(BORDER_COLOR)
|
304 |
spine.set_linewidth(0.75)
|
305 |
display_text = f"{hall}{end_time}"
|
306 |
-
|
307 |
-
# **修改点**: 移除 fontproperties,改用 fontsize
|
308 |
ax.text(0.5, 0.5, display_text,
|
309 |
-
|
310 |
-
fontweight='bold',
|
311 |
ha='center', va='center',
|
312 |
transform=ax.transAxes)
|
313 |
ax.set_xticks([])
|
314 |
ax.set_yticks([])
|
315 |
ax.set_facecolor('none')
|
316 |
ax_date = fig.add_subplot(gs[0, :])
|
317 |
-
|
318 |
-
# **修改点**: 移除 fontproperties,改用 fontsize
|
319 |
ax_date.text(0.01, 0.5, f"{date_str} {title}",
|
320 |
-
|
321 |
-
color=DATE_COLOR,
|
322 |
ha='left', va='center',
|
323 |
transform=ax_date.transAxes)
|
324 |
ax_date.set_axis_off()
|
@@ -374,7 +372,7 @@ if uploaded_file:
|
|
374 |
with col1:
|
375 |
st.subheader("白班 (散场时间 ≤ 17:30)")
|
376 |
if part1_output:
|
377 |
-
tab1_1, tab1_2 = st.tabs(["PDF 预览 ", "图片预览 (PNG) "])
|
378 |
with tab1_1:
|
379 |
st.markdown(display_pdf(part1_output['pdf']), unsafe_allow_html=True)
|
380 |
with tab1_2:
|
@@ -384,7 +382,7 @@ if uploaded_file:
|
|
384 |
with col2:
|
385 |
st.subheader("晚班 (散场时间 > 17:30)")
|
386 |
if part2_output:
|
387 |
-
tab2_1, tab2_2 = st.tabs(["PDF 预览 ", "图片预览 (PNG) "])
|
388 |
with tab2_1:
|
389 |
st.markdown(display_pdf(part2_output['pdf']), unsafe_allow_html=True)
|
390 |
with tab2_2:
|
|
|
23 |
NUM_COLS = 3
|
24 |
|
25 |
# --- 字体加载与文本处理函数 ---
|
26 |
+
|
27 |
+
def get_font_regular(size=14):
|
28 |
+
"""加载思源黑体-常规 (SourceHanSansCN-Regular.otf)"""
|
29 |
+
font_path = "SourceHanSansCN-Regular.otf"
|
|
|
30 |
if os.path.exists(font_path):
|
31 |
return font_manager.FontProperties(fname=font_path, size=size)
|
32 |
else:
|
33 |
+
st.warning("警告:未找到字体文件 'SourceHanSansCN-Regular.otf',LED屏排片表显示可能不正确。")
|
|
|
34 |
return font_manager.FontProperties(family='sans-serif', size=size)
|
35 |
|
36 |
+
def get_font_bold(size=14):
|
37 |
+
"""加载思源黑体-粗体 (SourceHanSansCN-Bold.otf)"""
|
38 |
+
font_path = "SourceHanSansCN-Bold.otf"
|
39 |
+
if os.path.exists(font_path):
|
40 |
+
return font_manager.FontProperties(fname=font_path, size=size)
|
41 |
+
else:
|
42 |
+
st.warning("警告:未找到字体文件 'SourceHanSansCN-Bold.otf',散场时间表显示可能不正确。")
|
43 |
+
return font_manager.FontProperties(family='sans-serif', size=size, weight='bold')
|
44 |
+
|
45 |
def get_pinyin_abbr(text):
|
46 |
"""获取中文文本前两个字的拼音首字母"""
|
47 |
if not text:
|
|
|
63 |
return circled_chars[n - 1]
|
64 |
return f'({n})'
|
65 |
|
66 |
+
# --- '放映时间核对表' 处理函数 ---
|
67 |
def process_schedule_led(file):
|
68 |
"""处理 '放映时间核对表.xls' 文件"""
|
69 |
try:
|
|
|
111 |
return None, date_str
|
112 |
|
113 |
def create_print_layout_led(data, date_str):
|
114 |
+
"""为 '放映时间核对表' 生成打印布局 (使用 Regular 字体)"""
|
115 |
if data is None or data.empty:
|
116 |
return None
|
117 |
A4_width_in, A4_height_in = 8.27, 11.69
|
|
|
131 |
|
132 |
def get_col_width_in(series, font_size_pt, is_math=False):
|
133 |
if series.empty: return 0
|
134 |
+
font_prop = get_font_regular(font_size_pt) # 使用 Regular 字体
|
135 |
longest_str_idx = series.astype(str).str.len().idxmax()
|
136 |
max_content = str(series.loc[longest_str_idx])
|
137 |
text_width_px, _, _ = renderer.get_text_width_height_descent(max_content, font_prop, ismath=is_math)
|
|
|
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
|
|
|
198 |
ax.set_xlim(0, A4_width_in)
|
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)
|
|
|
209 |
plt.close(fig)
|
210 |
return outputs
|
211 |
|
212 |
+
# --- '放映场次核对表' 处理函数 ---
|
213 |
def process_schedule_times(file):
|
214 |
"""处理 '放映场次核对表.xls' 文件"""
|
215 |
try:
|
|
|
217 |
df = df.iloc[:, [6, 7, 9]]
|
218 |
df.columns = ['Hall', 'StartTime', 'EndTime']
|
219 |
df = df.dropna(subset=['Hall', 'StartTime', 'EndTime'])
|
220 |
+
df['Hall'] = df['Hall'].str.extract(r'(\d+)号').astype(str) + ' '
|
221 |
base_date = datetime.today().date()
|
222 |
df['StartTime'] = pd.to_datetime(df['StartTime'])
|
223 |
df['EndTime'] = pd.to_datetime(df['EndTime'])
|
|
|
258 |
return None, None, None
|
259 |
|
260 |
def create_print_layout_times(data, title, date_str):
|
261 |
+
"""为 '放映场次核对表' 生成打印布局 (使用 Bold 字体)"""
|
262 |
if data.empty:
|
263 |
return None
|
264 |
|
|
|
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 |
+
|
281 |
gs = gridspec.GridSpec(
|
282 |
num_rows + 1, NUM_COLS,
|
283 |
hspace=0, wspace=0,
|
|
|
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 字体
|
|
|
311 |
ha='center', va='center',
|
312 |
transform=ax.transAxes)
|
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 字体
|
319 |
+
color=DATE_COLOR,
|
320 |
ha='left', va='center',
|
321 |
transform=ax_date.transAxes)
|
322 |
ax_date.set_axis_off()
|
|
|
372 |
with col1:
|
373 |
st.subheader("白班 (散场时间 ≤ 17:30)")
|
374 |
if part1_output:
|
375 |
+
tab1_1, tab1_2 = st.tabs(["PDF 预览 ", "图片预览 (PNG) "])
|
376 |
with tab1_1:
|
377 |
st.markdown(display_pdf(part1_output['pdf']), unsafe_allow_html=True)
|
378 |
with tab1_2:
|
|
|
382 |
with col2:
|
383 |
st.subheader("晚班 (散场时间 > 17:30)")
|
384 |
if part2_output:
|
385 |
+
tab2_1, tab2_2 = st.tabs(["PDF 预览 ", "图片预览 (PNG) "])
|
386 |
with tab2_1:
|
387 |
st.markdown(display_pdf(part2_output['pdf']), unsafe_allow_html=True)
|
388 |
with tab2_2:
|