Ed5 commited on
Commit
41ccc3b
·
verified ·
1 Parent(s): 4512ed0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -39
app.py CHANGED
@@ -18,21 +18,44 @@ class KDChecker:
18
  self.known_docs = ["Э3", "В4", "ПЭ3", "ВО", "ТЭ5", "СБ", "С5", "ОЛ", "Э1", "Э4", "Э7", "Д3", "Э6"]
19
 
20
  def load_excel_db(self, excel_path):
 
 
 
21
  if excel_path is None:
22
- return "Файл не выбран", gr.update(choices=[], value=None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  all_data = []
25
  sheets_log = []
26
 
27
  try:
28
- # --- ПРАВКА ДЛЯ СЕРВЕРА: явно указываем движок openpyxl ---
 
29
  xls = pd.read_excel(excel_path, sheet_name=None, header=None, engine='openpyxl')
 
30
 
31
  for sheet_name, df_raw in xls.items():
32
  header_row_index = -1
33
  cab_col_idx = -1
34
  rem_col_idx = -1
35
 
 
36
  for i in range(min(20, len(df_raw))):
37
  row_values = [str(x).lower().strip() for x in df_raw.iloc[i].values]
38
  c_idx = -1
@@ -64,17 +87,20 @@ class KDChecker:
64
  sheets_log.append(f"Лист '{sheet_name}': заголовки не найдены")
65
 
66
  if not all_data:
67
- return "❌ Ошибка: Не найдены заголовки 'Шкаф' и 'Примечание'.", gr.update(choices=[], value=None)
 
68
 
69
  self.excel_db = pd.concat(all_data, ignore_index=True)
70
  self.cabinet_list = sorted(self.excel_db["Cabinet"].unique().tolist())
71
-
 
72
  msg = f"✅ База знаний загружена успешно!\nВсего записей: {len(self.excel_db)}\nОбработаны листы: {', '.join(sheets_log)}"
73
  return msg, gr.update(choices=self.cabinet_list, value=None, interactive=True)
74
 
75
  except Exception as e:
76
- # Выводим ошибку прямо в интерфейс
77
- return f"КРИТИЧЕСКАЯ ОШИБКА EXCEL: {str(e)}", gr.update(choices=[], value=None)
 
78
 
79
  def extract_text(self, pdf_path):
80
  try:
@@ -114,7 +140,6 @@ class KDChecker:
114
 
115
  def get_remarks(self, cabinet_key, is_clean_key=True):
116
  if self.excel_db.empty: return {}
117
-
118
  if is_clean_key:
119
  target = cabinet_key.replace(" ", "")
120
  mask = self.excel_db['Cabinet_Clean'].str.contains(re.escape(target), case=False, na=False)
@@ -123,43 +148,31 @@ class KDChecker:
123
 
124
  rows = self.excel_db[mask]
125
  if rows.empty: return {}
126
-
127
  parsed = {}
128
-
129
  for remark_cell in rows['Remark']:
130
  cell_text = str(remark_cell)
131
  cell_text = re.sub(r'(\d+)\.([А-ЯA-Z])', r'\1. \2', cell_text)
132
-
133
  items = re.split(r'(?:^|\n)\s*(?=\d+[\.\)])', cell_text)
134
-
135
  for item in items:
136
  if len(item) < 3: continue
137
  clean_item = item.strip()
138
  clean_item_no_num = re.sub(r'^\d+[\.\)]\s*', '', clean_item)
139
-
140
  doc_pattern = r'^(?:Документ\s+|В\s+)?([А-ЯA-Z0-9\s,\(\)\-]+?)(?:[\.\:\-]|\s+)(.*)'
141
  match = re.match(doc_pattern, clean_item_no_num, re.IGNORECASE | re.DOTALL)
142
-
143
  detected_docs = []
144
  final_text = clean_item
145
-
146
  if match:
147
  potential_docs_str = match.group(1).upper()
148
  cleaned_codes = potential_docs_str.replace("(", " ").replace(")", " ").replace(",", " ")
149
  parts = cleaned_codes.split()
150
-
151
  valid_parts = [p for p in parts if p in self.known_docs]
152
  if valid_parts:
153
  detected_docs = valid_parts
154
  final_text = match.group(2).strip()
155
-
156
- if not detected_docs:
157
- detected_docs = ["ALL"]
158
-
159
  for doc in detected_docs:
160
  if doc not in parsed: parsed[doc] = []
161
  parsed[doc].append(final_text)
162
-
163
  return parsed
164
 
165
  def check_files(self, files, manual_cabinet):
@@ -226,11 +239,11 @@ class KDChecker:
226
  pdf_title = detected_cabinet
227
  if is_manual: pdf_title += " (Выбор вручную)"
228
 
229
- # --- ВАЖНО: Проверка создания PDF ---
230
  try:
231
  pdf = self.create_pdf(pdf_title, checklist)
232
  except Exception as e:
233
- return f"❌ Ошибка создания PDF: {e}\n(Возможно, не загружен шрифт arial.ttf?)", None
234
 
235
  total = sum(len(v) for v in checklist.values())
236
  method_str = "Ручной выбор" if is_manual else (
@@ -245,29 +258,26 @@ class KDChecker:
245
  form = c.acroForm
246
  width, height = A4
247
 
248
- # --- ПОИСК ШРИФТА ДЛЯ СЕРВЕРА ---
249
  font_name = 'Helvetica'
250
- font_path = "arial.ttf" # Файл должен лежать в Files на Hugging Face
251
 
252
  if os.path.exists(font_path):
253
  try:
254
  pdfmetrics.registerFont(TTFont('Arial', font_path))
255
  font_name = 'Arial'
256
  except:
257
- pass
258
-
259
- # Если шрифт не найден, но мы на сервере - это проблема.
260
- # Код попытается использовать Helvetica, но кириллица пропадет.
261
 
262
  y = height - 50
263
  c.setFont(font_name, 16)
264
 
265
- # Защита от ошибок кодировки при отсутствии шрифта
266
  try:
267
  c.drawString(50, y, f"ЧЕК-ЛИСТ ПРОВЕРКИ КД")
268
  except:
269
  c.setFont("Helvetica", 16)
270
- c.drawString(50, y, "CHECK-LIST (Font Error)")
271
  c.setFont(font_name, 16)
272
 
273
  y -= 25
@@ -278,7 +288,7 @@ class KDChecker:
278
  c.drawString(50, y, f"Шкаф: {disp_cab}")
279
  except:
280
  c.setFont("Helvetica", 12)
281
- c.drawString(50, y, "Cabinet: (Name Error)")
282
  c.setFont(font_name, 12)
283
 
284
  c.drawString(400, y, f"Дата: {datetime.now().strftime('%d.%m.%Y')}")
@@ -300,10 +310,10 @@ class KDChecker:
300
  try:
301
  c.drawString(50, y, f"Файл: {filename}")
302
  except:
303
- c.setFont("Helvetica", 11)
304
- c.drawString(50, y, f"File: {filename}")
305
- c.setFont(font_name, 11)
306
-
307
  c.setFillColor(colors.black)
308
  y -= 15
309
  c.setFont(font_name, 10)
@@ -339,13 +349,10 @@ class KDChecker:
339
  c.showPage();
340
  text_start_y = height - 50;
341
  c.setFont(font_name, 10)
342
-
343
  try:
344
  c.drawString(65, text_start_y, l.strip())
345
  except:
346
- # Игнорируем строки, которые нельзя напечатать без шрифта
347
- pass
348
-
349
  text_start_y -= 12
350
 
351
  y = text_start_y - 8
 
18
  self.known_docs = ["Э3", "В4", "ПЭ3", "ВО", "ТЭ5", "СБ", "С5", "ОЛ", "Э1", "Э4", "Э7", "Д3", "Э6"]
19
 
20
  def load_excel_db(self, excel_path):
21
+ # --- ЛОГГЕР ---
22
+ log = [f"[{datetime.now().strftime('%H:%M:%S')}] Старт функции загрузки"]
23
+
24
  if excel_path is None:
25
+ return "Файл не передан (excel_path is None)", gr.update(choices=[], value=None)
26
+
27
+ log.append(f"Путь к файлу: {excel_path}")
28
+
29
+ # Проверка размера файла (чтобы убедиться, что он загрузился)
30
+ try:
31
+ size = os.path.getsize(excel_path)
32
+ log.append(f"Размер файла: {size} байт")
33
+ except Exception as e:
34
+ log.append(f"Ошибка доступа к файлу: {e}")
35
+ return "\n".join(log), gr.update(choices=[], value=None)
36
+
37
+ # Проверка наличия движка
38
+ try:
39
+ import openpyxl
40
+ log.append("Библиотека openpyxl найдена.")
41
+ except ImportError:
42
+ return "ОШИБКА: Библиотека openpyxl не установлена на сервере!", gr.update(choices=[], value=None)
43
 
44
  all_data = []
45
  sheets_log = []
46
 
47
  try:
48
+ log.append("Попытка чтения Excel через pandas...")
49
+ # Явно указываем движок
50
  xls = pd.read_excel(excel_path, sheet_name=None, header=None, engine='openpyxl')
51
+ log.append(f"Файл прочитан. Найдены листы: {list(xls.keys())}")
52
 
53
  for sheet_name, df_raw in xls.items():
54
  header_row_index = -1
55
  cab_col_idx = -1
56
  rem_col_idx = -1
57
 
58
+ # Поиск заголовков
59
  for i in range(min(20, len(df_raw))):
60
  row_values = [str(x).lower().strip() for x in df_raw.iloc[i].values]
61
  c_idx = -1
 
87
  sheets_log.append(f"Лист '{sheet_name}': заголовки не найдены")
88
 
89
  if not all_data:
90
+ log.append("Не найдены данные ни на одном листе.")
91
+ return "\n".join(log), gr.update(choices=[], value=None)
92
 
93
  self.excel_db = pd.concat(all_data, ignore_index=True)
94
  self.cabinet_list = sorted(self.excel_db["Cabinet"].unique().tolist())
95
+
96
+ log.append("Успешно объединили данные.")
97
  msg = f"✅ База знаний загружена успешно!\nВсего записей: {len(self.excel_db)}\nОбработаны листы: {', '.join(sheets_log)}"
98
  return msg, gr.update(choices=self.cabinet_list, value=None, interactive=True)
99
 
100
  except Exception as e:
101
+ # Возвращаем полный лог ошибки
102
+ log.append(f"КРИТИЧЕСКАЯ ОШИБКА: {str(e)}")
103
+ return "\n".join(log), gr.update(choices=[], value=None)
104
 
105
  def extract_text(self, pdf_path):
106
  try:
 
140
 
141
  def get_remarks(self, cabinet_key, is_clean_key=True):
142
  if self.excel_db.empty: return {}
 
143
  if is_clean_key:
144
  target = cabinet_key.replace(" ", "")
145
  mask = self.excel_db['Cabinet_Clean'].str.contains(re.escape(target), case=False, na=False)
 
148
 
149
  rows = self.excel_db[mask]
150
  if rows.empty: return {}
 
151
  parsed = {}
 
152
  for remark_cell in rows['Remark']:
153
  cell_text = str(remark_cell)
154
  cell_text = re.sub(r'(\d+)\.([А-ЯA-Z])', r'\1. \2', cell_text)
 
155
  items = re.split(r'(?:^|\n)\s*(?=\d+[\.\)])', cell_text)
 
156
  for item in items:
157
  if len(item) < 3: continue
158
  clean_item = item.strip()
159
  clean_item_no_num = re.sub(r'^\d+[\.\)]\s*', '', clean_item)
 
160
  doc_pattern = r'^(?:Документ\s+|В\s+)?([А-ЯA-Z0-9\s,\(\)\-]+?)(?:[\.\:\-]|\s+)(.*)'
161
  match = re.match(doc_pattern, clean_item_no_num, re.IGNORECASE | re.DOTALL)
 
162
  detected_docs = []
163
  final_text = clean_item
 
164
  if match:
165
  potential_docs_str = match.group(1).upper()
166
  cleaned_codes = potential_docs_str.replace("(", " ").replace(")", " ").replace(",", " ")
167
  parts = cleaned_codes.split()
 
168
  valid_parts = [p for p in parts if p in self.known_docs]
169
  if valid_parts:
170
  detected_docs = valid_parts
171
  final_text = match.group(2).strip()
172
+ if not detected_docs: detected_docs = ["ALL"]
 
 
 
173
  for doc in detected_docs:
174
  if doc not in parsed: parsed[doc] = []
175
  parsed[doc].append(final_text)
 
176
  return parsed
177
 
178
  def check_files(self, files, manual_cabinet):
 
239
  pdf_title = detected_cabinet
240
  if is_manual: pdf_title += " (Выбор вручную)"
241
 
242
+ # Создание PDF с защитой от отсутствия шрифта
243
  try:
244
  pdf = self.create_pdf(pdf_title, checklist)
245
  except Exception as e:
246
+ return f"❌ Ошибка создания PDF: {e}", None
247
 
248
  total = sum(len(v) for v in checklist.values())
249
  method_str = "Ручной выбор" if is_manual else (
 
258
  form = c.acroForm
259
  width, height = A4
260
 
261
+ # Ищем шрифт на сервере
262
  font_name = 'Helvetica'
263
+ font_path = "arial.ttf" # Ожидаем в корне
264
 
265
  if os.path.exists(font_path):
266
  try:
267
  pdfmetrics.registerFont(TTFont('Arial', font_path))
268
  font_name = 'Arial'
269
  except:
270
+ pass # Если шрифт битый, останется Helvetica
 
 
 
271
 
272
  y = height - 50
273
  c.setFont(font_name, 16)
274
 
275
+ # Безопасная печать заголовка
276
  try:
277
  c.drawString(50, y, f"ЧЕК-ЛИСТ ПРОВЕРКИ КД")
278
  except:
279
  c.setFont("Helvetica", 16)
280
+ c.drawString(50, y, "CHECK-LIST")
281
  c.setFont(font_name, 16)
282
 
283
  y -= 25
 
288
  c.drawString(50, y, f"Шкаф: {disp_cab}")
289
  except:
290
  c.setFont("Helvetica", 12)
291
+ c.drawString(50, y, "Cabinet name error (font)")
292
  c.setFont(font_name, 12)
293
 
294
  c.drawString(400, y, f"Дата: {datetime.now().strftime('%d.%m.%Y')}")
 
310
  try:
311
  c.drawString(50, y, f"Файл: {filename}")
312
  except:
313
+ c.setFont("Helvetica", 11)
314
+ c.drawString(50, y, f"File: {filename}")
315
+ c.setFont(font_name, 11)
316
+
317
  c.setFillColor(colors.black)
318
  y -= 15
319
  c.setFont(font_name, 10)
 
349
  c.showPage();
350
  text_start_y = height - 50;
351
  c.setFont(font_name, 10)
 
352
  try:
353
  c.drawString(65, text_start_y, l.strip())
354
  except:
355
+ pass # Игнорируем непечатаемые символы
 
 
356
  text_start_y -= 12
357
 
358
  y = text_start_y - 8