Ed5 commited on
Commit
6761181
·
verified ·
1 Parent(s): 5dac689

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -25
app.py CHANGED
@@ -16,13 +16,13 @@ from reportlab.lib import colors
16
  class KDChecker:
17
  def __init__(self):
18
  self.excel_db = pd.DataFrame()
19
- self.cabinet_list = []
20
  self.known_docs = ["Э3", "В4", "ПЭ3", "ВО", "ТЭ5", "СБ", "С5", "ОЛ", "Э1", "Э4", "Э7", "Д3", "Э6"]
21
 
22
  def load_excel_db(self, excel_path):
23
  print(f"--- Загрузка Excel: {excel_path} ---")
24
  if excel_path is None:
25
- return "Файл не выбран", gr.update(choices=[], value=None)
 
26
 
27
  all_data = []
28
  sheets_log = []
@@ -52,6 +52,9 @@ class KDChecker:
52
  df = pd.read_excel(excel_path, sheet_name=sheet_name, header=header_row_index)
53
  df_subset = df.iloc[:, [cab_col_idx, rem_col_idx]]
54
  df_subset.columns = ["Cabinet", "Remark"]
 
 
 
55
  df_subset["Cabinet"] = df_subset["Cabinet"].ffill()
56
  df_subset = df_subset.dropna(subset=["Remark"]).astype(str)
57
  df_subset["Cabinet_Clean"] = df_subset["Cabinet"].apply(
@@ -61,25 +64,37 @@ class KDChecker:
61
  sheets_log.append(f"'{sheet_name}': {len(df_subset)}")
62
 
63
  if not all_data:
64
- return "❌ Ошибка: Не найдены заголовки 'Шкаф' и 'Примечание'.", gr.update(choices=[], value=None)
65
 
66
  self.excel_db = pd.concat(all_data, ignore_index=True)
67
- self.cabinet_list = sorted(self.excel_db["Cabinet"].unique().tolist())
 
 
68
 
69
  print(f"Excel загружен. Всего строк: {len(self.excel_db)}")
70
- msg = f"✅ База загружена!\nЗаписей: {len(self.excel_db)}\nЛисты: {', '.join(sheets_log)}"
71
- return msg, gr.update(choices=self.cabinet_list, value=None, interactive=True)
 
 
72
 
73
  except Exception as e:
74
  print(f"Ошибка Excel: {e}")
75
- return f"❌ Ошибка: {e}", gr.update(choices=[], value=None)
 
 
 
 
 
 
 
 
 
76
 
77
  def extract_text(self, pdf_path):
78
  text = ""
79
  try:
80
  with pdfplumber.open(pdf_path) as pdf:
81
- # Читаем только первые 2 страницы для скорости, обычно номер там
82
- # Если нужно читать весь файл - уберите [:2]
83
  for page in pdf.pages[:5]:
84
  text += (page.extract_text() or "") + "\n"
85
  except Exception as e:
@@ -164,35 +179,27 @@ class KDChecker:
164
  found_by_method = "manual"
165
  is_manual = True
166
  else:
167
- # === ОПТИМИЗАЦИЯ: Читаем файлы по очереди и прерываемся, если нашли ===
168
  db_clean_keys = set(self.excel_db["Cabinet_Clean"].tolist())
169
 
170
  for file_path in progress.tqdm(files, desc="Поиск номера шкафа"):
171
  text = self.extract_text(file_path)
172
  pdf_numbers = self.find_all_decimal_numbers(text)
173
 
174
- # Проверяем, есть ли найденные номера в базе
175
  for cand in pdf_numbers:
176
  if cand in db_clean_keys:
177
  detected_cabinet = cand
178
  found_by_method = "number"
179
- break # Прерываем поиск по номерам в текущем файле
180
 
181
  if found_by_method == "number":
182
  print(f"✅ Шкаф найден в файле: {os.path.basename(file_path)}")
183
- break # Прерываем чтение остальных файлов!
184
-
185
- # Если по номерам не нашли, пробуем по имени (тоже не читаем все подряд)
186
- if detected_cabinet == "Не определен":
187
- # Здесь сложнее, так как имя может быть в любом файле.
188
- # Но если мы уже прочитали часть файлов и не нашли номер,
189
- # скорее всего это ручной ввод.
190
- pass
191
 
192
  print(f"Определен шкаф: {detected_cabinet}")
193
 
194
  if detected_cabinet == "Не определен":
195
- return f"⚠️ Шкаф не опознан автоматически.\nВыберите шкаф вручную.", None
196
 
197
  is_clean_search = (found_by_method == "number")
198
  remarks = self.get_remarks(detected_cabinet, is_clean_key=is_clean_search)
@@ -200,7 +207,6 @@ class KDChecker:
200
  if not remarks:
201
  return f"⚠️ Для шкафа '{detected_cabinet}' нет замечаний в базе.", None
202
 
203
- # Формируем список задач (здесь уже не читаем PDF, только имена файлов)
204
  processed_count = 0
205
  for file_path in files:
206
  fname = os.path.basename(file_path)
@@ -329,14 +335,28 @@ def create_app():
329
  gr.Markdown("## ✅ Генератор чек-листов КД")
330
 
331
  with gr.Row():
 
332
  with gr.Column(scale=1):
333
  gr.Markdown("### 1. База знаний")
334
  db_in = gr.File(label="Excel (.xlsx)", type="filepath", elem_classes="compact_file")
 
 
335
  with gr.Group():
336
- manual_cab = gr.Dropdown(label="Или шкаф вручную", choices=[], interactive=True)
 
 
 
 
 
337
  db_out = gr.Textbox(label="Статус базы", lines=2, max_lines=3, interactive=False)
338
- db_in.upload(checker.load_excel_db, inputs=[db_in], outputs=[db_out, manual_cab])
339
 
 
 
 
 
 
 
 
340
  with gr.Column(scale=1):
341
  gr.Markdown("### 2. Документация")
342
  files_in = gr.File(label="Чертежи (PDF)", file_count="multiple", type="filepath", elem_classes="compact_file")
@@ -350,7 +370,7 @@ def create_app():
350
  with gr.Column(scale=1):
351
  res_pdf = gr.File(label="Скачать готовый PDF")
352
 
353
- btn.click(checker.check_files, inputs=[files_in, manual_cab], outputs=[res_txt, res_pdf])
354
 
355
  return app
356
 
 
16
  class KDChecker:
17
  def __init__(self):
18
  self.excel_db = pd.DataFrame()
 
19
  self.known_docs = ["Э3", "В4", "ПЭ3", "ВО", "ТЭ5", "СБ", "С5", "ОЛ", "Э1", "Э4", "Э7", "Д3", "Э6"]
20
 
21
  def load_excel_db(self, excel_path):
22
  print(f"--- Загрузка Excel: {excel_path} ---")
23
  if excel_path is None:
24
+ # Возвращаем: Сообщение, Пустой список авторов, Пустой список шкафов
25
+ return "Файл не выбран", gr.update(choices=[], value=None), gr.update(choices=[], value=None)
26
 
27
  all_data = []
28
  sheets_log = []
 
52
  df = pd.read_excel(excel_path, sheet_name=sheet_name, header=header_row_index)
53
  df_subset = df.iloc[:, [cab_col_idx, rem_col_idx]]
54
  df_subset.columns = ["Cabinet", "Remark"]
55
+ # Добавляем колонку с именем листа (Автором)
56
+ df_subset["Author"] = sheet_name
57
+
58
  df_subset["Cabinet"] = df_subset["Cabinet"].ffill()
59
  df_subset = df_subset.dropna(subset=["Remark"]).astype(str)
60
  df_subset["Cabinet_Clean"] = df_subset["Cabinet"].apply(
 
64
  sheets_log.append(f"'{sheet_name}': {len(df_subset)}")
65
 
66
  if not all_data:
67
+ return "❌ Ошибка: Не найдены заголовки 'Шкаф' и 'Примечание'.", gr.update(choices=[]), gr.update(choices=[])
68
 
69
  self.excel_db = pd.concat(all_data, ignore_index=True)
70
+
71
+ # Получаем список уникальных авторов (листов)
72
+ authors_list = sorted(self.excel_db["Author"].unique().tolist())
73
 
74
  print(f"Excel загружен. Всего строк: {len(self.excel_db)}")
75
+ msg = f"✅ База загружена!\nЗаписей: {len(self.excel_db)}\nАвторы: {', '.join(sheets_log)}"
76
+
77
+ # Возвращаем: Статус, Список авторов, Очищаем список шкафов
78
+ return msg, gr.update(choices=authors_list, value=None, interactive=True), gr.update(choices=[], value=None)
79
 
80
  except Exception as e:
81
  print(f"Ошибка Excel: {e}")
82
+ return f"❌ Ошибка: {e}", gr.update(choices=[]), gr.update(choices=[])
83
+
84
+ def get_cabinets_by_author(self, author_name):
85
+ """Фильтрует шкафы по выбранному автору"""
86
+ if self.excel_db.empty or not author_name:
87
+ return gr.update(choices=[], value=None)
88
+
89
+ # Фильтруем базу по автору
90
+ filtered_cabs = self.excel_db[self.excel_db["Author"] == author_name]["Cabinet"].unique().tolist()
91
+ return gr.update(choices=sorted(filtered_cabs), value=None, interactive=True)
92
 
93
  def extract_text(self, pdf_path):
94
  text = ""
95
  try:
96
  with pdfplumber.open(pdf_path) as pdf:
97
+ # Читаем первые 5 страниц для скорости поиска номера
 
98
  for page in pdf.pages[:5]:
99
  text += (page.extract_text() or "") + "\n"
100
  except Exception as e:
 
179
  found_by_method = "manual"
180
  is_manual = True
181
  else:
182
+ # === ОПТИМИЗАЦИЯ ===
183
  db_clean_keys = set(self.excel_db["Cabinet_Clean"].tolist())
184
 
185
  for file_path in progress.tqdm(files, desc="Поиск номера шкафа"):
186
  text = self.extract_text(file_path)
187
  pdf_numbers = self.find_all_decimal_numbers(text)
188
 
 
189
  for cand in pdf_numbers:
190
  if cand in db_clean_keys:
191
  detected_cabinet = cand
192
  found_by_method = "number"
193
+ break
194
 
195
  if found_by_method == "number":
196
  print(f"✅ Шкаф найден в файле: {os.path.basename(file_path)}")
197
+ break
 
 
 
 
 
 
 
198
 
199
  print(f"Определен шкаф: {detected_cabinet}")
200
 
201
  if detected_cabinet == "Не определен":
202
+ return f"⚠️ Шкаф не опознан автоматически.\nВыберите Автора и Шкаф вручную.", None
203
 
204
  is_clean_search = (found_by_method == "number")
205
  remarks = self.get_remarks(detected_cabinet, is_clean_key=is_clean_search)
 
207
  if not remarks:
208
  return f"⚠️ Для шкафа '{detected_cabinet}' нет замечаний в базе.", None
209
 
 
210
  processed_count = 0
211
  for file_path in files:
212
  fname = os.path.basename(file_path)
 
335
  gr.Markdown("## ✅ Генератор чек-листов КД")
336
 
337
  with gr.Row():
338
+ # --- ЛЕВАЯ КОЛОНКА: БАЗА ---
339
  with gr.Column(scale=1):
340
  gr.Markdown("### 1. База знаний")
341
  db_in = gr.File(label="Excel (.xlsx)", type="filepath", elem_classes="compact_file")
342
+
343
+ # Группа ручного выбора
344
  with gr.Group():
345
+ gr.Markdown("#### Ручной выбор (если автопоиск не сработал):")
346
+ # Сначала выбираем автора
347
+ author_dd = gr.Dropdown(label="1. Автор (Лист Excel)", choices=[], interactive=True)
348
+ # Затем шкаф (зависит от автора)
349
+ cabinet_dd = gr.Dropdown(label="2. Выберите шкаф", choices=[], interactive=True)
350
+
351
  db_out = gr.Textbox(label="Статус базы", lines=2, max_lines=3, interactive=False)
 
352
 
353
+ # Событие загрузки Excel: обновляет статус и список авторов
354
+ db_in.upload(checker.load_excel_db, inputs=[db_in], outputs=[db_out, author_dd, cabinet_dd])
355
+
356
+ # Событие выбора автора: фильтрует список шкафов
357
+ author_dd.change(checker.get_cabinets_by_author, inputs=[author_dd], outputs=[cabinet_dd])
358
+
359
+ # --- ПРАВАЯ КОЛОНКА: ЧЕРТЕЖИ ---
360
  with gr.Column(scale=1):
361
  gr.Markdown("### 2. Документация")
362
  files_in = gr.File(label="Чертежи (PDF)", file_count="multiple", type="filepath", elem_classes="compact_file")
 
370
  with gr.Column(scale=1):
371
  res_pdf = gr.File(label="Скачать готовый PDF")
372
 
373
+ btn.click(checker.check_files, inputs=[files_in, cabinet_dd], outputs=[res_txt, res_pdf])
374
 
375
  return app
376