초기 프로젝트 설정 및 데이터베이스 관련 파일 추가: .gitignore, 데이터베이스 관리 클래스, UI 컴포넌트, 데이터베이스 테이블 생성 및 데이터 처리 기능 구현
This commit is contained in:
parent
4321621873
commit
0f256ce444
|
|
@ -0,0 +1,9 @@
|
|||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
*.pyw
|
||||
*.pyz
|
||||
*.pywz
|
||||
.venv/
|
||||
~$*
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import sqlite3
|
||||
|
||||
def check_database():
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 테이블 목록 확인
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
||||
tables = cursor.fetchall()
|
||||
print("테이블 목록:", tables)
|
||||
|
||||
# woojin200 테이블의 데이터 확인
|
||||
cursor.execute("SELECT * FROM woojin200 LIMIT 5;")
|
||||
rows = cursor.fetchall()
|
||||
print("\n첫 5개 데이터:")
|
||||
for row in rows:
|
||||
print(row)
|
||||
|
||||
# 전체 데이터 개수 확인
|
||||
cursor.execute("SELECT COUNT(*) FROM woojin200;")
|
||||
count = cursor.fetchone()[0]
|
||||
print(f"\n전체 데이터 개수: {count}")
|
||||
|
||||
# 테이블 구조 확인
|
||||
cursor.execute("PRAGMA table_info(woojin200);")
|
||||
columns = cursor.fetchall()
|
||||
print("\n테이블 구조:")
|
||||
for col in columns:
|
||||
print(col)
|
||||
|
||||
conn.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
check_database()
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
import sqlite3
|
||||
import re
|
||||
|
||||
def clean_text(text):
|
||||
"""
|
||||
텍스트에서 불필요한 접두어를 제거합니다.
|
||||
|
||||
Args:
|
||||
text (str): 정제할 텍스트
|
||||
|
||||
Returns:
|
||||
str: 정제된 텍스트
|
||||
"""
|
||||
if not text:
|
||||
return text
|
||||
|
||||
# 다양한 접두어 제거
|
||||
prefixes = [
|
||||
"반응 : ", "반응\n1)", "반응\n0)",
|
||||
"검지조건 : ", "검지조건\n1)", "검지조건\n0)",
|
||||
"소거 : ", "소거조건\n1)", "소거조건\n0)",
|
||||
"조치방법 : ", "조치방법\n1)", "조치방법\n0)",
|
||||
"관련도면 : ", "관련도면\n1)", "관련도면\n0)"
|
||||
]
|
||||
|
||||
for prefix in prefixes:
|
||||
text = text.replace(prefix, '').strip()
|
||||
|
||||
return text.strip()
|
||||
|
||||
def extract_drawing(text):
|
||||
"""
|
||||
"회로 도면 : "으로 시작하는 내용을 추출합니다.
|
||||
|
||||
Args:
|
||||
text (str): 원본 텍스트
|
||||
|
||||
Returns:
|
||||
tuple: (정제된 action, drawing)
|
||||
"""
|
||||
if not text:
|
||||
return text, None
|
||||
|
||||
# 회로 도면 추출
|
||||
drawing_match = re.search(r'회로 도면 : (.+)', text)
|
||||
drawing = drawing_match.group(1).strip() if drawing_match else None
|
||||
|
||||
# 회로 도면 부분 제거
|
||||
if drawing:
|
||||
text = re.sub(r'회로 도면 : .+', '', text).strip()
|
||||
|
||||
return text, drawing
|
||||
|
||||
def clean_database():
|
||||
"""데이터베이스의 레코드를 정제합니다."""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 테이블의 모든 레코드 가져오기
|
||||
cursor.execute("SELECT * FROM woojin200")
|
||||
records = cursor.fetchall()
|
||||
|
||||
# 컬럼 이름 가져오기
|
||||
cursor.execute("PRAGMA table_info(woojin200)")
|
||||
columns = [column[1] for column in cursor.fetchall()]
|
||||
|
||||
# 업데이트할 레코드 준비
|
||||
updated_records = []
|
||||
|
||||
for record in records:
|
||||
record_dict = dict(zip(columns, record))
|
||||
|
||||
# 각 텍스트 필드 정제
|
||||
record_dict['reaction'] = clean_text(record_dict['reaction'])
|
||||
record_dict['detect_condition'] = clean_text(record_dict['detect_condition'])
|
||||
record_dict['clear_condition'] = clean_text(record_dict['clear_condition'])
|
||||
|
||||
# action에서 drawing 추출
|
||||
record_dict['action'], record_dict['drawing'] = extract_drawing(record_dict['action'])
|
||||
record_dict['action'] = clean_text(record_dict['action'])
|
||||
|
||||
# 업데이트할 레코드 준비
|
||||
updated_record = tuple(record_dict[col] for col in columns)
|
||||
updated_records.append(updated_record)
|
||||
|
||||
# 테이블 업데이트
|
||||
cursor.execute("DELETE FROM woojin200")
|
||||
cursor.executemany(f"""
|
||||
INSERT INTO woojin200 ({','.join(columns)})
|
||||
VALUES ({','.join(['?']*len(columns))})
|
||||
""", updated_records)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print("데이터베이스 정제 완료!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
clean_database()
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"""
|
||||
데이터베이스 관리 패키지
|
||||
"""
|
||||
|
||||
from .db_manager import DatabaseManager
|
||||
|
||||
__all__ = ['DatabaseManager']
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import sqlite3
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
class DatabaseManager:
|
||||
"""데이터베이스 관리 클래스"""
|
||||
|
||||
def __init__(self, db_path: str = "fault_codes.db"):
|
||||
"""
|
||||
데이터베이스 매니저 초기화
|
||||
Args:
|
||||
db_path (str): 데이터베이스 파일 경로
|
||||
"""
|
||||
self.db_path = db_path
|
||||
self._create_tables()
|
||||
|
||||
def _create_tables(self):
|
||||
"""필요한 테이블 생성"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 고장 코드 테이블 생성
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS fault_codes (
|
||||
code TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
solution TEXT
|
||||
)
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def search_fault_codes(self, search_term: str) -> List[Dict[str, str]]:
|
||||
"""
|
||||
고장 코드 검색
|
||||
Args:
|
||||
search_term (str): 검색어
|
||||
Returns:
|
||||
List[Dict[str, str]]: 검색 결과 목록
|
||||
"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
if search_term:
|
||||
# 코드나 설명에서 검색어 찾기
|
||||
cursor.execute('''
|
||||
SELECT fault_code, fault_name, fault_level, fault_type,
|
||||
fault_detail, reaction, detect_condition, clear_condition, action
|
||||
FROM woojin200
|
||||
WHERE fault_name LIKE ? OR fault_detail LIKE ?
|
||||
ORDER BY fault_code
|
||||
''', (f'%{search_term}%', f'%{search_term}%'))
|
||||
else:
|
||||
# 전체 목록 가져오기
|
||||
cursor.execute('''
|
||||
SELECT fault_code, fault_name, fault_level, fault_type,
|
||||
fault_detail, reaction, detect_condition, clear_condition, action
|
||||
FROM woojin200
|
||||
ORDER BY fault_code
|
||||
''')
|
||||
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
return [
|
||||
{
|
||||
'code': str(code),
|
||||
'description': f"[{level}] {name} - {detail}",
|
||||
'solution': f"조치방법:\n{action}\n\n검지조건:\n{detect}\n\n소거조건:\n{clear}"
|
||||
}
|
||||
for code, name, level, type_, detail, reaction, detect, clear, action in results
|
||||
]
|
||||
|
||||
def add_fault(self, code: str, description: str, solution: Optional[str] = None,
|
||||
category: Optional[str] = None) -> bool:
|
||||
"""
|
||||
새로운 고장 코드를 추가합니다.
|
||||
|
||||
Args:
|
||||
code (str): 고장 코드
|
||||
description (str): 설명
|
||||
solution (Optional[str]): 해결 방법
|
||||
category (Optional[str]): 카테고리
|
||||
|
||||
Returns:
|
||||
bool: 추가 성공 여부
|
||||
"""
|
||||
try:
|
||||
with sqlite3.connect(self.db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
INSERT INTO fault_codes (code, description, solution, category)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (code, description, solution, category))
|
||||
conn.commit()
|
||||
return True
|
||||
except sqlite3.Error:
|
||||
return False
|
||||
|
||||
def __del__(self):
|
||||
"""데이터베이스 연결을 종료합니다."""
|
||||
if hasattr(self, 'conn'):
|
||||
self.conn.close()
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
from typing import Dict, List
|
||||
import pandas as pd
|
||||
import sqlite3
|
||||
import uuid
|
||||
|
||||
|
||||
def create_woojin200_table():
|
||||
"""우진200 차량의 고장 코드 테이블을 생성합니다."""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 우진200 테이블 생성
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS woojin200 (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code_id TEXT UNIQUE, -- UUID
|
||||
fault_code TEXT, -- 고장코드
|
||||
fault_name TEXT, -- 고장명
|
||||
fault_level TEXT, -- 등급
|
||||
fault_type TEXT, -- 분류
|
||||
fault_detail TEXT, -- 고장내용
|
||||
reaction TEXT, -- 반응
|
||||
detect_condition TEXT, -- 검지조건
|
||||
clear_condition TEXT, -- 소거조건
|
||||
action TEXT -- 조치방법
|
||||
)
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_rotem200_table():
|
||||
"""로템200 차량의 고장 코드 테이블을 생성합니다."""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 로템200 테이블 생성
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS rotem200 (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code_id TEXT UNIQUE, -- UUID
|
||||
fault_code TEXT, -- 고장코드
|
||||
fault_name TEXT, -- 고장명
|
||||
fault_level TEXT, -- 등급
|
||||
fault_type TEXT, -- 분류
|
||||
fault_detail TEXT, -- 고장내용
|
||||
reaction TEXT, -- 반응
|
||||
detect_condition TEXT, -- 검지조건
|
||||
clear_condition TEXT, -- 소거조건
|
||||
action TEXT -- 조치방법
|
||||
)
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def import_excel_to_sqlite():
|
||||
"""엑셀 파일에서 고장 코드 데이터를 읽어 SQLite 데이터베이스에 저장합니다."""
|
||||
try:
|
||||
# 엑셀 파일 읽기
|
||||
df = pd.read_excel(
|
||||
'우진200백데이터.xlsx',
|
||||
sheet_name='200량 고장해설',
|
||||
header=0
|
||||
)
|
||||
|
||||
print("엑셀 파일의 열 이름:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# UUID 생성
|
||||
df['code_id'] = [str(uuid.uuid4()) for _ in range(len(df))]
|
||||
|
||||
# 열 이름 매핑
|
||||
column_mapping = {
|
||||
'고장코드': 'fault_code',
|
||||
'고장명': 'fault_name',
|
||||
'등급': 'fault_level',
|
||||
'분류': 'fault_type',
|
||||
'고장내용': 'fault_detail',
|
||||
'반응': 'reaction',
|
||||
'검지조건': 'detect_condition',
|
||||
'소거조건': 'clear_condition',
|
||||
'조치방법': 'action'
|
||||
}
|
||||
|
||||
# 열 이름 변경
|
||||
df = df.rename(columns=column_mapping)
|
||||
|
||||
# SQLite 연결
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
|
||||
# 데이터프레임을 SQLite 테이블에 저장
|
||||
df.to_sql('woojin200', conn, if_exists='replace', index=False)
|
||||
|
||||
# 변경사항 저장 및 연결 종료
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print("데이터가 성공적으로 SQLite 데이터베이스에 저장되었습니다.")
|
||||
|
||||
# 저장된 데이터 확인
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT COUNT(*) FROM woojin200")
|
||||
count = cursor.fetchone()[0]
|
||||
print(f"총 {count}개의 레코드가 저장되었습니다.")
|
||||
|
||||
# 샘플 데이터 출력
|
||||
cursor.execute("SELECT * FROM woojin200 LIMIT 5")
|
||||
sample_data = cursor.fetchall()
|
||||
print("\n샘플 데이터:")
|
||||
for row in sample_data:
|
||||
print(row)
|
||||
|
||||
conn.close()
|
||||
|
||||
except (FileNotFoundError, pd.errors.EmptyDataError) as e:
|
||||
print(f"엑셀 파일 오류: {str(e)}")
|
||||
except sqlite3.Error as e:
|
||||
print(f"데이터베이스 오류: {str(e)}")
|
||||
|
||||
def import_excel_to_rotem200():
|
||||
"""엑셀 파일에서 고장 코드 데이터를 읽어 SQLite 데이터베이스에 저장합니다."""
|
||||
try:
|
||||
# 엑셀 파일 읽기
|
||||
df = pd.read_excel(
|
||||
'로템200백데이터.xlsx',
|
||||
sheet_name='200량 고장해설',
|
||||
header=0
|
||||
)
|
||||
|
||||
print("엑셀 파일의 열 이름:")
|
||||
print(df.columns.tolist())
|
||||
|
||||
# UUID 생성
|
||||
df['code_id'] = [str(uuid.uuid4()) for _ in range(len(df))]
|
||||
|
||||
# 열 이름 매핑
|
||||
column_mapping = {
|
||||
'고장코드': 'fault_code',
|
||||
'고장명': 'fault_name',
|
||||
'등급': 'fault_level',
|
||||
'분류': 'fault_type',
|
||||
'고장내용': 'fault_detail',
|
||||
'반응': 'reaction',
|
||||
'검지조건': 'detect_condition',
|
||||
'소거조건': 'clear_condition',
|
||||
'조치방법': 'action'
|
||||
}
|
||||
|
||||
# 열 이름 변경
|
||||
df = df.rename(columns=column_mapping)
|
||||
|
||||
# SQLite 연결
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
|
||||
# 데이터프레임을 SQLite 테이블에 저장
|
||||
df.to_sql('rotem200', conn, if_exists='replace', index=False)
|
||||
|
||||
# 변경사항 저장 및 연결 종료
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print("데이터가 성공적으로 SQLite 데이터베이스에 저장되었습니다.")
|
||||
|
||||
# 저장된 데이터 확인
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT COUNT(*) FROM rotem200")
|
||||
count = cursor.fetchone()[0]
|
||||
print(f"총 {count}개의 레코드가 저장되었습니다.")
|
||||
|
||||
# 샘플 데이터 출력
|
||||
cursor.execute("SELECT * FROM rotem200 LIMIT 5")
|
||||
sample_data = cursor.fetchall()
|
||||
print("\n샘플 데이터:")
|
||||
for row in sample_data:
|
||||
print(row)
|
||||
|
||||
conn.close()
|
||||
|
||||
except (FileNotFoundError, pd.errors.EmptyDataError) as e:
|
||||
print(f"엑셀 파일 오류: {str(e)}")
|
||||
except sqlite3.Error as e:
|
||||
print(f"데이터베이스 오류: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_woojin200_table()
|
||||
create_rotem200_table()
|
||||
import_excel_to_sqlite()
|
||||
import_excel_to_rotem200()
|
||||
Binary file not shown.
|
|
@ -0,0 +1,33 @@
|
|||
import flet as ft
|
||||
from database.db_manager import DatabaseManager
|
||||
from ui.fault_finder import FaultFinderUI
|
||||
|
||||
def main(page: ft.Page):
|
||||
"""
|
||||
메인 애플리케이션을 초기화하고 실행합니다.
|
||||
|
||||
Args:
|
||||
page (ft.Page): Flet 페이지 객체
|
||||
"""
|
||||
# 페이지 설정
|
||||
page.title = "고장코드 검색기"
|
||||
page.theme_mode = ft.ThemeMode.LIGHT
|
||||
page.padding = 20
|
||||
page.window_width = 400 # 세로 모드에 맞는 너비
|
||||
page.window_height = 800 # 세로 모드에 맞는 높이
|
||||
page.window_resizable = False # 창 크기 고정
|
||||
|
||||
# 데이터베이스 매니저 초기화
|
||||
db_manager = DatabaseManager()
|
||||
|
||||
# UI 컴포넌트 초기화
|
||||
fault_finder = FaultFinderUI(page, db_manager)
|
||||
|
||||
# 메인 컨테이너를 페이지에 추가
|
||||
page.add(fault_finder.container)
|
||||
|
||||
# 초기 로딩 시 전체 코드 목록 표시
|
||||
fault_finder.load_all_codes()
|
||||
|
||||
if __name__ == "__main__":
|
||||
ft.app(target=main)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,16 @@
|
|||
[tool.poetry]
|
||||
name = "fault-code-finder"
|
||||
version = "0.1.0"
|
||||
description = "고장 코드 검색 애플리케이션"
|
||||
authors = ["Your Name <your.email@example.com>"]
|
||||
package-mode = false
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
flet = "^0.21.0"
|
||||
pandas = "^2.2.0"
|
||||
openpyxl = "^3.1.2"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"""
|
||||
UI 컴포넌트 패키지
|
||||
"""
|
||||
|
||||
from .fault_finder import FaultFinderUI
|
||||
|
||||
__all__ = ['FaultFinderUI']
|
||||
|
|
@ -0,0 +1,430 @@
|
|||
import flet as ft
|
||||
import sqlite3
|
||||
from typing import List, Dict, Callable
|
||||
from database.db_manager import DatabaseManager
|
||||
|
||||
class FaultFinderUI:
|
||||
"""고장코드 검색 UI를 관리하는 클래스입니다."""
|
||||
|
||||
def __init__(self, page: ft.Page, db_manager: DatabaseManager):
|
||||
"""
|
||||
FaultFinderUI를 초기화합니다.
|
||||
|
||||
Args:
|
||||
page (ft.Page): Flet 페이지 객체
|
||||
db_manager (DatabaseManager): 데이터베이스 관리자 인스턴스
|
||||
"""
|
||||
self.page = page
|
||||
self.db_manager = db_manager
|
||||
|
||||
# 전체 제작사 목록 가져오기
|
||||
self.manufacturers = self._get_manufacturers()
|
||||
|
||||
# 상단: 제작사 필터
|
||||
self.manufacturer_dropdown = ft.Dropdown(
|
||||
label="제작사 선택",
|
||||
options=[
|
||||
ft.dropdown.Option(manufacturer) for manufacturer in self.manufacturers
|
||||
],
|
||||
on_change=self._on_manufacturer_change,
|
||||
expand=True
|
||||
)
|
||||
|
||||
# 전체 고장 타입 목록 가져오기
|
||||
self.fault_types = self._get_fault_types()
|
||||
|
||||
# 상단: 고장 타입 필터
|
||||
self.type_dropdown = ft.Dropdown(
|
||||
label="장치분류 선택",
|
||||
options=[
|
||||
ft.dropdown.Option(type_) for type_ in self.fault_types
|
||||
],
|
||||
on_change=self._on_type_change,
|
||||
expand=True
|
||||
)
|
||||
|
||||
# 중앙: 고장 리스트
|
||||
self.fault_list = ft.DataTable(
|
||||
columns=[
|
||||
ft.DataColumn(ft.Text("고장코드")),
|
||||
ft.DataColumn(ft.Text("고장명")),
|
||||
ft.DataColumn(ft.Text("고장타입"))
|
||||
],
|
||||
rows=[],
|
||||
expand=True,
|
||||
show_bottom_border=True,
|
||||
column_spacing=10,
|
||||
horizontal_lines=ft.border.BorderSide(1, "grey")
|
||||
)
|
||||
|
||||
# 중앙 리스트 컨테이너 (스크롤 가능하도록)
|
||||
self.fault_list_container = ft.Container(
|
||||
content=ft.ListView(
|
||||
controls=[self.fault_list],
|
||||
expand=True,
|
||||
spacing=10,
|
||||
padding=10,
|
||||
auto_scroll=True
|
||||
),
|
||||
expand=True,
|
||||
border=ft.border.all(1, ft.colors.GREY_300),
|
||||
border_radius=10
|
||||
)
|
||||
|
||||
# 하단: 검색 필드
|
||||
self.search_field = ft.TextField(
|
||||
label="검색어 입력",
|
||||
hint_text="고장코드나 고장명을 입력하세요",
|
||||
expand=True,
|
||||
on_change=self._on_search_change,
|
||||
prefix_icon=ft.icons.SEARCH
|
||||
)
|
||||
|
||||
# 메인 컨테이너
|
||||
self.container = ft.Container(
|
||||
content=ft.Column([
|
||||
# 상단: 제작사 필터
|
||||
ft.Container(
|
||||
content=self.manufacturer_dropdown,
|
||||
padding=10,
|
||||
bgcolor=ft.colors.BLUE_GREY_50,
|
||||
border_radius=10
|
||||
),
|
||||
|
||||
# 상단: 고장 타입 필터
|
||||
ft.Container(
|
||||
content=self.type_dropdown,
|
||||
padding=10,
|
||||
bgcolor=ft.colors.BLUE_GREY_50,
|
||||
border_radius=10
|
||||
),
|
||||
|
||||
# 중앙: 고장 리스트
|
||||
self.fault_list_container,
|
||||
|
||||
# 하단: 검색 필드
|
||||
ft.Container(
|
||||
content=self.search_field,
|
||||
padding=10,
|
||||
bgcolor=ft.colors.BLUE_GREY_50,
|
||||
border_radius=10
|
||||
)
|
||||
], spacing=10),
|
||||
expand=True,
|
||||
padding=10
|
||||
)
|
||||
|
||||
# 초기 로딩
|
||||
self.load_all_codes()
|
||||
|
||||
def _get_manufacturers(self) -> List[str]:
|
||||
"""
|
||||
제작사 목록을 가져옵니다.
|
||||
|
||||
Returns:
|
||||
List[str]: 제작사 목록
|
||||
"""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT DISTINCT manufacturers FROM woojin200 ORDER BY manufacturers")
|
||||
manufacturers = [manufacturer[0] for manufacturer in cursor.fetchall()]
|
||||
conn.close()
|
||||
return manufacturers
|
||||
|
||||
def _get_fault_types(self) -> List[str]:
|
||||
"""
|
||||
고장 타입 목록을 가져옵니다.
|
||||
|
||||
Returns:
|
||||
List[str]: 고장 타입 목록
|
||||
"""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT DISTINCT fault_type FROM woojin200 ORDER BY fault_type")
|
||||
types = [type_[0] for type_ in cursor.fetchall()]
|
||||
conn.close()
|
||||
return types
|
||||
|
||||
def load_all_codes(self):
|
||||
"""전체 고장 코드 목록을 로드합니다."""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
ORDER BY fault_code
|
||||
""")
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
self._update_fault_list(results)
|
||||
|
||||
def _on_manufacturer_change(self, e):
|
||||
"""
|
||||
제작사 선택 시 호출되는 콜백 함수입니다.
|
||||
|
||||
Args:
|
||||
e: 드롭다운 변경 이벤트
|
||||
"""
|
||||
selected_manufacturer = self.manufacturer_dropdown.value
|
||||
selected_type = self.type_dropdown.value
|
||||
|
||||
if selected_manufacturer:
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 제작사만 선택된 경우
|
||||
if not selected_type:
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
WHERE manufacturers = ?
|
||||
ORDER BY fault_code
|
||||
""", (selected_manufacturer,))
|
||||
# 제작사와 고장 타입 모두 선택된 경우
|
||||
else:
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
WHERE manufacturers = ? AND fault_type = ?
|
||||
ORDER BY fault_code
|
||||
""", (selected_manufacturer, selected_type))
|
||||
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
self._update_fault_list(results)
|
||||
else:
|
||||
# 제작사 선택 해제 시 현재 선택된 고장 타입으로 필터링
|
||||
self._on_type_change(e)
|
||||
|
||||
def _on_type_change(self, e):
|
||||
"""
|
||||
고장 타입 선택 시 호출되는 콜백 함수입니다.
|
||||
|
||||
Args:
|
||||
e: 드롭다운 변경 이벤트
|
||||
"""
|
||||
selected_type = self.type_dropdown.value
|
||||
selected_manufacturer = self.manufacturer_dropdown.value
|
||||
|
||||
if selected_type:
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 고장 타입만 선택된 경우
|
||||
if not selected_manufacturer:
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
WHERE fault_type = ?
|
||||
ORDER BY fault_code
|
||||
""", (selected_type,))
|
||||
# 제작사와 고장 타입 모두 선택된 경우
|
||||
else:
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
WHERE fault_type = ? AND manufacturers = ?
|
||||
ORDER BY fault_code
|
||||
""", (selected_type, selected_manufacturer))
|
||||
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
self._update_fault_list(results)
|
||||
else:
|
||||
# 고장 타입 선택 해제 시 현재 선택된 제작사로 필터링
|
||||
self._on_manufacturer_change(e)
|
||||
|
||||
def _on_search_change(self, e):
|
||||
"""
|
||||
검색어 변경 시 호출되는 콜백 함수입니다.
|
||||
|
||||
Args:
|
||||
e: 검색 필드 변경 이벤트
|
||||
"""
|
||||
search_term = self.search_field.value
|
||||
selected_type = self.type_dropdown.value
|
||||
selected_manufacturer = self.manufacturer_dropdown.value
|
||||
|
||||
if search_term:
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 장치분류가 선택되지 않은 경우 전체 검색
|
||||
if not selected_type:
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
WHERE fault_code LIKE ? OR fault_name LIKE ?
|
||||
ORDER BY fault_code
|
||||
""", (f'%{search_term}%', f'%{search_term}%'))
|
||||
# 장치분류가 선택된 경우 해당 분류 내에서 검색
|
||||
else:
|
||||
cursor.execute("""
|
||||
SELECT fault_code, fault_name, fault_type
|
||||
FROM woojin200
|
||||
WHERE fault_type = ? AND (fault_code LIKE ? OR fault_name LIKE ?)
|
||||
ORDER BY fault_code
|
||||
""", (selected_type, f'%{search_term}%', f'%{search_term}%'))
|
||||
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
self._update_fault_list(results)
|
||||
else:
|
||||
# 검색어가 없으면 현재 선택된 필터로 다시 로드
|
||||
if selected_type:
|
||||
self._on_type_change(e)
|
||||
elif selected_manufacturer:
|
||||
self._on_manufacturer_change(e)
|
||||
else:
|
||||
self.load_all_codes()
|
||||
|
||||
def _update_fault_list(self, results):
|
||||
"""
|
||||
고장 리스트를 업데이트합니다.
|
||||
|
||||
Args:
|
||||
results (List[Tuple]): 고장 코드 결과 목록
|
||||
"""
|
||||
rows = []
|
||||
for code, name, type_ in results:
|
||||
row = ft.DataRow(
|
||||
cells=[
|
||||
ft.DataCell(ft.Text(str(code))),
|
||||
ft.DataCell(ft.Text(name)),
|
||||
ft.DataCell(ft.Text(type_))
|
||||
],
|
||||
on_select_changed=lambda e, code=code, name=name, type_=type_: self._show_fault_details(code, name, type_)
|
||||
)
|
||||
rows.append(row)
|
||||
|
||||
self.fault_list.rows = rows
|
||||
self.page.update()
|
||||
|
||||
def _show_fault_details(self, code, name, type_):
|
||||
"""
|
||||
고장 상세 정보를 팝업으로 표시합니다.
|
||||
|
||||
Args:
|
||||
code (str): 고장 코드
|
||||
name (str): 고장명
|
||||
type_ (str): 고장 타입
|
||||
"""
|
||||
conn = sqlite3.connect('fault_codes.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT fault_detail, reaction, detect_condition, clear_condition, action
|
||||
FROM woojin200
|
||||
WHERE fault_code = ?
|
||||
""", (code,))
|
||||
details = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
if details:
|
||||
detail, reaction, detect, clear, action = details
|
||||
|
||||
# 상세 정보 다이얼로그 생성
|
||||
dialog = ft.AlertDialog(
|
||||
title=ft.Text(f"[{code}] {name}", weight=ft.FontWeight.BOLD),
|
||||
content=ft.Column([
|
||||
ft.Text("고장 타입: " + type_, color=ft.colors.BLUE_GREY_700),
|
||||
ft.Divider(),
|
||||
ft.Text("고장 상세:", weight=ft.FontWeight.BOLD),
|
||||
ft.Text(detail, selectable=True),
|
||||
ft.Divider(),
|
||||
ft.Text("반응:", weight=ft.FontWeight.BOLD),
|
||||
ft.Text(reaction, selectable=True),
|
||||
ft.Divider(),
|
||||
ft.Text("검지 조건:", weight=ft.FontWeight.BOLD),
|
||||
ft.Text(detect, selectable=True),
|
||||
ft.Divider(),
|
||||
ft.Text("소거 조건:", weight=ft.FontWeight.BOLD),
|
||||
ft.Text(clear, selectable=True),
|
||||
ft.Divider(),
|
||||
ft.Text("조치 방법:", weight=ft.FontWeight.BOLD),
|
||||
ft.Text(action, selectable=True)
|
||||
], width=500, height=500, scroll=ft.ScrollMode.AUTO),
|
||||
actions=[
|
||||
ft.TextButton("닫기", on_click=lambda e: self._close_dialog())
|
||||
]
|
||||
)
|
||||
|
||||
self.page.dialog = dialog
|
||||
dialog.open = True
|
||||
self.page.update()
|
||||
|
||||
def _close_dialog(self):
|
||||
"""
|
||||
다이얼로그를 닫는 메서드입니다.
|
||||
"""
|
||||
if self.page.dialog:
|
||||
self.page.dialog.open = False
|
||||
self.page.update()
|
||||
|
||||
def create_search_field(self, on_change: Callable) -> ft.TextField:
|
||||
"""검색 필드를 생성합니다."""
|
||||
self.search_field = ft.TextField(
|
||||
label="검색",
|
||||
hint_text="고장코드, 고장명, 분류 등을 입력하세요",
|
||||
on_change=on_change,
|
||||
expand=True
|
||||
)
|
||||
return self.search_field
|
||||
|
||||
def create_data_table(self, data: List) -> ft.DataTable:
|
||||
"""검색 결과로 데이터 테이블을 생성합니다."""
|
||||
columns = [
|
||||
ft.DataColumn(ft.Text("고장코드")),
|
||||
ft.DataColumn(ft.Text("고장명")),
|
||||
ft.DataColumn(ft.Text("등급")),
|
||||
ft.DataColumn(ft.Text("분류")),
|
||||
ft.DataColumn(ft.Text("고장내용"), numeric=False),
|
||||
ft.DataColumn(ft.Text("반응")),
|
||||
ft.DataColumn(ft.Text("검지조건")),
|
||||
ft.DataColumn(ft.Text("소거조건")),
|
||||
ft.DataColumn(ft.Text("조치방법"))
|
||||
]
|
||||
|
||||
rows = []
|
||||
for row in data:
|
||||
cells = [ft.DataCell(ft.Text(str(cell))) for cell in row]
|
||||
rows.append(ft.DataRow(cells=cells))
|
||||
|
||||
self.data_table = ft.DataTable(
|
||||
columns=columns,
|
||||
rows=rows,
|
||||
border=ft.border.all(1, "grey"),
|
||||
border_radius=10,
|
||||
vertical_lines=ft.border.BorderSide(1, "grey"),
|
||||
horizontal_lines=ft.border.BorderSide(1, "grey"),
|
||||
)
|
||||
return self.data_table
|
||||
|
||||
def update_table(self, data: List):
|
||||
"""테이블 데이터를 업데이트합니다."""
|
||||
new_table = self.create_data_table(data)
|
||||
self.data_table.columns = new_table.columns
|
||||
self.data_table.rows = new_table.rows
|
||||
|
||||
def create_layout(self) -> ft.Column:
|
||||
"""메인 레이아웃을 생성합니다."""
|
||||
return ft.Column([
|
||||
ft.Container(
|
||||
content=self.search_field,
|
||||
padding=10,
|
||||
),
|
||||
ft.Container(
|
||||
content=ft.Column([
|
||||
ft.Text("검색 결과", size=20, weight=ft.FontWeight.BOLD),
|
||||
ft.Container(
|
||||
content=self.data_table,
|
||||
height=500,
|
||||
)
|
||||
]),
|
||||
padding=10,
|
||||
expand=True,
|
||||
)
|
||||
])
|
||||
Binary file not shown.
Loading…
Reference in New Issue