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:
|