Ed5 commited on
Commit
ada24b4
·
verified ·
1 Parent(s): 85de60d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -153
app.py CHANGED
@@ -11,16 +11,16 @@ from reportlab.pdfbase import pdfmetrics
11
  from reportlab.pdfbase.ttfonts import TTFont
12
  from reportlab.lib import colors
13
 
14
- # ========== НАСТРОЙКИ АВТОРИЗАЦИИ ==========
15
  AUTH_USERNAME = "admin"
16
  AUTH_PASSWORD = "12345"
17
- # ===========================================
18
 
19
- print("===== Application Startup =====")
20
- print(f"Time: {datetime.now()}")
21
- print(f"Gradio version: {gr.__version__}")
22
  print(f"Auth: {AUTH_USERNAME} / *****")
23
- print("================================")
24
 
25
 
26
  class KDChecker:
@@ -28,41 +28,22 @@ class KDChecker:
28
  self.excel_db = pd.DataFrame()
29
  self.cabinet_list = []
30
  self.known_docs = ["Э3", "В4", "ПЭ3", "ВО", "ТЭ5", "СБ", "С5", "ОЛ", "Э1", "Э4", "Э7", "Д3", "Э6"]
31
- print("[KDChecker] Initialized")
32
 
33
  def load_excel_db(self, excel_file):
34
- """Загрузка Excel базы знаний"""
35
- log = [f"[{datetime.now().strftime('%H:%M:%S')}] Начало загрузки"]
36
-
37
  if excel_file is None:
38
- return "❌ Файл не выбран", gr.Dropdown.update(choices=[], value=None)
39
-
40
- # Получаем путь к файлу
41
- if isinstance(excel_file, str):
42
- excel_path = excel_file
43
- else:
44
- excel_path = excel_file.name if hasattr(excel_file, 'name') else str(excel_file)
45
 
46
- log.append(f"Путь: {excel_path}")
47
- log.append(f"Тип: {type(excel_file)}")
48
 
49
  if not os.path.exists(excel_path):
50
- log.append(f"❌ Файл не найден!")
51
- return "\n".join(log), gr.Dropdown.update(choices=[], value=None)
52
-
53
- try:
54
- file_size = os.path.getsize(excel_path)
55
- log.append(f"Размер: {file_size} байт")
56
- except Exception as e:
57
- log.append(f"Ошибка размера: {e}")
58
 
59
  all_data = []
60
  sheets_info = []
61
 
62
  try:
63
- log.append("Читаю Excel...")
64
  xls = pd.read_excel(excel_path, sheet_name=None, header=None, engine='openpyxl')
65
- log.append(f"Листов найдено: {len(xls)}")
66
 
67
  for sheet_name, df_raw in xls.items():
68
  header_row = -1
@@ -80,7 +61,7 @@ class KDChecker:
80
  header_row = i
81
  break
82
 
83
- if header_row != -1:
84
  df = pd.read_excel(excel_path, sheet_name=sheet_name, header=header_row, engine='openpyxl')
85
  if cab_col < len(df.columns) and rem_col < len(df.columns):
86
  df_sub = df.iloc[:, [cab_col, rem_col]]
@@ -94,24 +75,21 @@ class KDChecker:
94
  sheets_info.append(f"'{sheet_name}': {len(df_sub)}")
95
 
96
  if not all_data:
97
- log.append("❌ Данные не найдены ни на одном листе")
98
- return "\n".join(log), gr.Dropdown.update(choices=[], value=None)
99
 
100
  self.excel_db = pd.concat(all_data, ignore_index=True)
101
  self.cabinet_list = sorted(self.excel_db["Cabinet"].unique().tolist())
102
 
103
- result = f"✅ База загружена!\n\n"
104
- result += f"📊 Записей: {len(self.excel_db)}\n"
105
- result += f"🗄️ Шкафов: {len(self.cabinet_list)}\n"
106
- result += f"📋 Листы: {', '.join(sheets_info)}"
107
 
108
- return result, gr.Dropdown.update(choices=self.cabinet_list, value=None)
109
 
110
  except Exception as e:
111
- log.append(f"❌ ОШИБКА: {str(e)}")
112
  import traceback
113
- log.append(traceback.format_exc())
114
- return "\n".join(log), gr.Dropdown.update(choices=[], value=None)
115
 
116
  def extract_text(self, pdf_path):
117
  try:
@@ -134,19 +112,15 @@ class KDChecker:
134
 
135
  def determine_doc_type(self, filename):
136
  fname = filename.upper()
137
- if "С2" in fname: return "С2"
138
- if "ПЭ3" in fname or "ПЕРЕЧЕНЬ" in fname: return "ПЭ3"
139
- if3" in fname or "СХЕМА ЭЛЕКТРИЧЕСКАЯ" in fname: return3"
140
- if "Э4" in fname: return "Э4"
141
- if "В4" in fname or "СПЕЦИФИКАЦИЯ" in fname: return "В4"
142
- if "ВО" in fname or "Э7" in fname or "ГАБАРИТ" in fname: return "ВО"
143
- if "ТЭ5" in fname or "ТАБЛИЦА" in fname: return "ТЭ5"
144
- if "СБ" in fname: return "СБ"
145
- if "С5" in fname: return "С5"
146
- if "ОЛ" in fname: return "ОЛ"
147
- if "Э1" in fname: return "Э1"
148
- if "Э6" in fname or "ЗАЗЕМЛЕНИЯ" in fname: return "Э6"
149
- if "Д3" in fname or "МОНТАЖ" in fname: return "Д3"
150
  return "UNKNOWN"
151
 
152
  def get_remarks(self, cabinet_key, is_clean=True):
@@ -203,17 +177,13 @@ class KDChecker:
203
  if not files:
204
  return "❌ Загрузите PDF файлы", None
205
  if self.excel_db.empty:
206
- return "❌ Сначала загрузите Excel базу!", None
207
 
208
- # Получаем пути к файлам
209
  file_paths = []
210
  for f in files:
211
- if isinstance(f, str):
212
- file_paths.append(f)
213
- else:
214
- file_paths.append(f.name if hasattr(f, 'name') else str(f))
215
 
216
- checklist = {}
217
  detected_cabinet = "Не определен"
218
  method = ""
219
  is_manual = False
@@ -223,10 +193,7 @@ class KDChecker:
223
  method = "manual"
224
  is_manual = True
225
  else:
226
- all_text = ""
227
- for fp in file_paths:
228
- all_text += self.extract_text(fp) + "\n"
229
-
230
  numbers = self.find_decimal_numbers(all_text)
231
  db_keys = set(self.excel_db["Cabinet_Clean"].tolist())
232
 
@@ -244,85 +211,65 @@ class KDChecker:
244
  detected_cabinet = cab
245
  method = "name"
246
  break
247
- if method == "name":
248
  break
249
 
250
  if detected_cabinet == "Не определен":
251
- return "⚠️ Шкаф не определён. Выберите вручную из списка.", None
252
-
253
- is_clean = (method == "number")
254
- remarks = self.get_remarks(detected_cabinet, is_clean=is_clean)
255
 
 
256
  if not remarks:
257
- return f"⚠️ Шкаф '{detected_cabinet}' найден, но замечаний нет.", None
258
 
 
259
  for fp in file_paths:
260
  fname = os.path.basename(fp)
261
  dtype = self.determine_doc_type(fname)
262
-
263
- tasks = []
264
- if dtype in remarks:
265
- tasks.extend(remarks[dtype])
266
- if "ALL" in remarks and dtype != "С2":
267
- tasks.extend(remarks["ALL"])
268
-
269
  if tasks:
270
  checklist[fname] = list(dict.fromkeys(tasks))
271
 
272
- title = detected_cabinet
273
- if is_manual:
274
- title += " (ручной выбор)"
275
-
276
  try:
277
  pdf_path = self.create_pdf(title, checklist)
278
  except Exception as e:
279
  return f"❌ Ошибка PDF: {e}", None
280
 
281
  total = sum(len(v) for v in checklist.values())
282
- method_str = "Ручной" if is_manual else ("По номеру" if is_clean else "По названию")
283
-
284
- result = f"✅ Готово!\n\n"
285
- result += f"📂 Шкаф: {detected_cabinet}\n"
286
- result += f"🔍 Метод: {method_str}\n"
287
- result += f"📄 Файлов: {len(file_paths)}\n"
288
- result += f"🚩 Замечаний: {total}"
289
 
290
- return result, pdf_path
291
 
292
  def create_pdf(self, cabinet, data):
293
  path = os.path.join(tempfile.gettempdir(), "CheckList.pdf")
294
  c = canvas.Canvas(path, pagesize=A4)
295
- width, height = A4
296
  font = 'Helvetica'
297
 
298
- y = height - 50
299
  c.setFont(font, 16)
300
- c.drawString(50, y, "CHECK-LIST KD")
301
-
302
  y -= 25
303
  c.setFont(font, 12)
304
- cab_display = cabinet[:50] + "..." if len(cabinet) > 50 else cabinet
305
- c.drawString(50, y, f"Cabinet: {cab_display}")
306
- c.drawString(400, y, f"Date: {datetime.now().strftime('%d.%m.%Y')}")
307
-
308
  y -= 20
309
- c.line(50, y, width - 50, y)
310
  y -= 30
311
 
312
  if not data:
313
- c.drawString(50, y, "No remarks for loaded files.")
314
  c.save()
315
  return path
316
 
317
- for filename, tasks in data.items():
318
  if y < 100:
319
  c.showPage()
320
- y = height - 50
321
- c.setFont(font, 12)
322
-
323
  c.setFillColor(colors.darkblue)
324
  c.setFont(font, 11)
325
- c.drawString(50, y, f"File: {filename}")
326
  c.setFillColor(colors.black)
327
  y -= 18
328
  c.setFont(font, 10)
@@ -330,85 +277,64 @@ class KDChecker:
330
  for task in tasks:
331
  if y < 60:
332
  c.showPage()
333
- y = height - 50
334
  c.setFont(font, 10)
335
-
336
  c.rect(50, y - 2, 8, 8, stroke=1, fill=0)
337
-
338
- # Разбивка на строки
339
  words = task.replace('\n', ' ').split()
340
- lines = []
341
- line = ""
342
- for w in words:
343
- if len(line) + len(w) < 85:
344
- line += w + " "
345
  else:
346
  lines.append(line.strip())
347
- line = w + " "
348
  if line:
349
  lines.append(line.strip())
350
 
351
- for i, ln in enumerate(lines):
352
  if y < 40:
353
  c.showPage()
354
- y = height - 50
355
  c.setFont(font, 10)
356
  c.drawString(65, y, ln)
357
  y -= 12
358
-
359
  y -= 5
360
-
361
  y -= 15
362
- c.setStrokeColor(colors.lightgrey)
363
- c.line(50, y, width - 50, y)
364
- c.setStrokeColor(colors.black)
365
- y -= 10
366
 
367
  c.save()
368
  return path
369
 
370
 
371
- # ========== СОЗДАНИЕ ИНТЕРФЕЙСА ==========
372
  checker = KDChecker()
373
 
374
- with gr.Blocks(title="КД Checker") as app:
375
  gr.Markdown("# ✅ Генератор чек-листов КД")
376
- gr.Markdown("Загрузите Excel базу и PDF чертежи для формирования чек-листа.")
377
-
378
  with gr.Row():
379
  with gr.Column():
380
- gr.Markdown("### 📁 1. База знаний (Excel)")
381
- db_input = gr.File(label="Загрузить .xlsx файл", file_types=[".xlsx", ".xls"])
382
- cabinet_dropdown = gr.Dropdown(label="Или выберите шкаф вручную", choices=[], interactive=True)
383
- db_status = gr.Textbox(label="Статус", lines=6)
384
-
385
  with gr.Column():
386
- gr.Markdown("### 📄 2. Чертежи (PDF)")
387
- pdf_input = gr.File(label="Загрузить PDF", file_count="multiple", file_types=[".pdf"])
388
- run_btn = gr.Button("🔍 Сф��рмировать чек-лист", variant="primary")
389
 
390
  with gr.Row():
391
- result_text = gr.Textbox(label="Результат", lines=6)
392
- result_pdf = gr.File(label="📥 Скачать PDF")
393
-
394
- # События
395
- db_input.change(
396
- fn=checker.load_excel_db,
397
- inputs=[db_input],
398
- outputs=[db_status, cabinet_dropdown]
399
- )
400
-
401
- run_btn.click(
402
- fn=checker.check_files,
403
- inputs=[pdf_input, cabinet_dropdown],
404
- outputs=[result_text, result_pdf]
405
- )
406
-
407
- # ========== ЗАПУСК ==========
408
  if __name__ == "__main__":
409
  app.launch(
410
  server_name="0.0.0.0",
411
  server_port=7860,
412
- auth=(AUTH_USERNAME, AUTH_PASSWORD),
413
- auth_message="Введите логин и пароль"
414
  )
 
11
  from reportlab.pdfbase.ttfonts import TTFont
12
  from reportlab.lib import colors
13
 
14
+ # ========== АВТОРИЗАЦИЯ ==========
15
  AUTH_USERNAME = "admin"
16
  AUTH_PASSWORD = "12345"
17
+ # =================================
18
 
19
+ print("=" * 40)
20
+ print(f"App Start: {datetime.now()}")
21
+ print(f"Gradio: {gr.__version__}")
22
  print(f"Auth: {AUTH_USERNAME} / *****")
23
+ print("=" * 40)
24
 
25
 
26
  class KDChecker:
 
28
  self.excel_db = pd.DataFrame()
29
  self.cabinet_list = []
30
  self.known_docs = ["Э3", "В4", "ПЭ3", "ВО", "ТЭ5", "СБ", "С5", "ОЛ", "Э1", "Э4", "Э7", "Д3", "Э6"]
 
31
 
32
  def load_excel_db(self, excel_file):
33
+ """Загрузка Excel базы"""
 
 
34
  if excel_file is None:
35
+ return "❌ Файл не выбран", gr.update(choices=[], value=None)
 
 
 
 
 
 
36
 
37
+ excel_path = excel_file if isinstance(excel_file, str) else getattr(excel_file, 'name', str(excel_file))
 
38
 
39
  if not os.path.exists(excel_path):
40
+ return f"❌ Файл не найден: {excel_path}", gr.update(choices=[], value=None)
 
 
 
 
 
 
 
41
 
42
  all_data = []
43
  sheets_info = []
44
 
45
  try:
 
46
  xls = pd.read_excel(excel_path, sheet_name=None, header=None, engine='openpyxl')
 
47
 
48
  for sheet_name, df_raw in xls.items():
49
  header_row = -1
 
61
  header_row = i
62
  break
63
 
64
+ if header_row != -1 and cab_col < len(df_raw.columns) and rem_col < len(df_raw.columns):
65
  df = pd.read_excel(excel_path, sheet_name=sheet_name, header=header_row, engine='openpyxl')
66
  if cab_col < len(df.columns) and rem_col < len(df.columns):
67
  df_sub = df.iloc[:, [cab_col, rem_col]]
 
75
  sheets_info.append(f"'{sheet_name}': {len(df_sub)}")
76
 
77
  if not all_data:
78
+ return "❌ Не найдены колонки 'Шкаф' и 'Примечание'", gr.update(choices=[], value=None)
 
79
 
80
  self.excel_db = pd.concat(all_data, ignore_index=True)
81
  self.cabinet_list = sorted(self.excel_db["Cabinet"].unique().tolist())
82
 
83
+ msg = f"✅ База загружена!\n\n"
84
+ msg += f"📊 Записей: {len(self.excel_db)}\n"
85
+ msg += f"🗄️ Шкафов: {len(self.cabinet_list)}\n"
86
+ msg += f"📋 Листы: {', '.join(sheets_info)}"
87
 
88
+ return msg, gr.update(choices=self.cabinet_list, value=None)
89
 
90
  except Exception as e:
 
91
  import traceback
92
+ return f"❌ Ошибка: {e}\n\n{traceback.format_exc()}", gr.update(choices=[], value=None)
 
93
 
94
  def extract_text(self, pdf_path):
95
  try:
 
112
 
113
  def determine_doc_type(self, filename):
114
  fname = filename.upper()
115
+ doc_map = {
116
+ "С2": ["С2"], "ПЭ3": ["ПЭ3", "ПЕРЕЧЕНЬ"], "Э3": ["Э3", "СХЕМА ЭЛЕКТРИЧЕСКАЯ"],
117
+ "Э4": [4"], "В4": ["В4", "СПЕЦИФИКАЦИЯ"], "ВО": ["ВО",7", "ГАБАРИТ"],
118
+ "ТЭ5": ["ТЭ5", "ТАБЛИЦА"], "СБ": ["СБ"], "С5": ["С5"], "ОЛ": ["ОЛ"],
119
+ "Э1": ["Э1"], "Э6": ["Э6", "ЗАЗЕМЛЕНИЯ"], "Д3": ["Д3", "МОНТАЖ"]
120
+ }
121
+ for doc_type, patterns in doc_map.items():
122
+ if any(p in fname for p in patterns):
123
+ return doc_type
 
 
 
 
124
  return "UNKNOWN"
125
 
126
  def get_remarks(self, cabinet_key, is_clean=True):
 
177
  if not files:
178
  return "❌ Загрузите PDF файлы", None
179
  if self.excel_db.empty:
180
+ return "❌ Сначала загрузите Excel!", None
181
 
 
182
  file_paths = []
183
  for f in files:
184
+ fp = f if isinstance(f, str) else getattr(f, 'name', str(f))
185
+ file_paths.append(fp)
 
 
186
 
 
187
  detected_cabinet = "Не определен"
188
  method = ""
189
  is_manual = False
 
193
  method = "manual"
194
  is_manual = True
195
  else:
196
+ all_text = "".join(self.extract_text(fp) for fp in file_paths)
 
 
 
197
  numbers = self.find_decimal_numbers(all_text)
198
  db_keys = set(self.excel_db["Cabinet_Clean"].tolist())
199
 
 
211
  detected_cabinet = cab
212
  method = "name"
213
  break
214
+ if method:
215
  break
216
 
217
  if detected_cabinet == "Не определен":
218
+ return "⚠️ Шкаф не определён. Выберите вручную.", None
 
 
 
219
 
220
+ remarks = self.get_remarks(detected_cabinet, is_clean=(method == "number"))
221
  if not remarks:
222
+ return f"⚠️ Для '{detected_cabinet}' замечаний нет.", None
223
 
224
+ checklist = {}
225
  for fp in file_paths:
226
  fname = os.path.basename(fp)
227
  dtype = self.determine_doc_type(fname)
228
+ tasks = remarks.get(dtype, []) + (remarks.get("ALL", []) if dtype != "С2" else [])
 
 
 
 
 
 
229
  if tasks:
230
  checklist[fname] = list(dict.fromkeys(tasks))
231
 
232
+ title = detected_cabinet + (" (ручной)" if is_manual else "")
233
+
 
 
234
  try:
235
  pdf_path = self.create_pdf(title, checklist)
236
  except Exception as e:
237
  return f"❌ Ошибка PDF: {e}", None
238
 
239
  total = sum(len(v) for v in checklist.values())
240
+ method_name = {"manual": "Ручной", "number": "По номеру", "name": "По названию"}.get(method, "?")
 
 
 
 
 
 
241
 
242
+ return f"✅ Готово!\n\n📂 {detected_cabinet}\n🔍 {method_name}\n📄 Файлов: {len(file_paths)}\n🚩 Замечаний: {total}", pdf_path
243
 
244
  def create_pdf(self, cabinet, data):
245
  path = os.path.join(tempfile.gettempdir(), "CheckList.pdf")
246
  c = canvas.Canvas(path, pagesize=A4)
247
+ w, h = A4
248
  font = 'Helvetica'
249
 
250
+ y = h - 50
251
  c.setFont(font, 16)
252
+ c.drawString(50, y, "CHECK-LIST")
 
253
  y -= 25
254
  c.setFont(font, 12)
255
+ c.drawString(50, y, f"Cabinet: {cabinet[:50]}")
256
+ c.drawString(400, y, datetime.now().strftime('%d.%m.%Y'))
 
 
257
  y -= 20
258
+ c.line(50, y, w - 50, y)
259
  y -= 30
260
 
261
  if not data:
262
+ c.drawString(50, y, "No remarks.")
263
  c.save()
264
  return path
265
 
266
+ for fname, tasks in data.items():
267
  if y < 100:
268
  c.showPage()
269
+ y = h - 50
 
 
270
  c.setFillColor(colors.darkblue)
271
  c.setFont(font, 11)
272
+ c.drawString(50, y, f"File: {fname}")
273
  c.setFillColor(colors.black)
274
  y -= 18
275
  c.setFont(font, 10)
 
277
  for task in tasks:
278
  if y < 60:
279
  c.showPage()
280
+ y = h - 50
281
  c.setFont(font, 10)
 
282
  c.rect(50, y - 2, 8, 8, stroke=1, fill=0)
283
+
 
284
  words = task.replace('\n', ' ').split()
285
+ lines, line = [], ""
286
+ for word in words:
287
+ if len(line) + len(word) < 85:
288
+ line += word + " "
 
289
  else:
290
  lines.append(line.strip())
291
+ line = word + " "
292
  if line:
293
  lines.append(line.strip())
294
 
295
+ for ln in lines:
296
  if y < 40:
297
  c.showPage()
298
+ y = h - 50
299
  c.setFont(font, 10)
300
  c.drawString(65, y, ln)
301
  y -= 12
 
302
  y -= 5
 
303
  y -= 15
 
 
 
 
304
 
305
  c.save()
306
  return path
307
 
308
 
309
+ # ========== ИНТЕРФЕЙС ==========
310
  checker = KDChecker()
311
 
312
+ with gr.Blocks(title="КД Checker", theme=gr.themes.Soft()) as app:
313
  gr.Markdown("# ✅ Генератор чек-листов КД")
314
+
 
315
  with gr.Row():
316
  with gr.Column():
317
+ gr.Markdown("### 📁 База знаний")
318
+ db_input = gr.File(label="Excel (.xlsx)", file_types=[".xlsx", ".xls"], type="filepath")
319
+ cabinet_dd = gr.Dropdown(label="Шкаф вручную", choices=[], interactive=True)
320
+ db_status = gr.Textbox(label="Статус", lines=5)
321
+
322
  with gr.Column():
323
+ gr.Markdown("### 📄 Чертежи")
324
+ pdf_input = gr.File(label="PDF файлы", file_count="multiple", file_types=[".pdf"], type="filepath")
325
+ run_btn = gr.Button("🔍 Сформировать", variant="primary")
326
 
327
  with gr.Row():
328
+ result_txt = gr.Textbox(label="Результат", lines=5)
329
+ result_pdf = gr.File(label="📥 PDF")
330
+
331
+ db_input.change(checker.load_excel_db, [db_input], [db_status, cabinet_dd])
332
+ run_btn.click(checker.check_files, [pdf_input, cabinet_dd], [result_txt, result_pdf])
333
+
334
+
 
 
 
 
 
 
 
 
 
 
335
  if __name__ == "__main__":
336
  app.launch(
337
  server_name="0.0.0.0",
338
  server_port=7860,
339
+ auth=(AUTH_USERNAME, AUTH_PASSWORD)
 
340
  )