""" وحدة مقارنة الملفات """ import streamlit as st import pandas as pd import random from datetime import datetime import difflib class FileComparisonApp: """ وحدة مقارنة الملفات للنظام """ def __init__(self): """ تهيئة وحدة مقارنة الملفات """ # تهيئة حالة الجلسة الخاصة بمقارنة الملفات إذا لم تكن موجودة if 'comparison_history' not in st.session_state: # إنشاء بيانات تجريبية لسجل المقارنات st.session_state.comparison_history = self._generate_sample_history() def run(self): """ تشغيل وحدة مقارنة الملفات """ st.markdown("

وحدة مقارنة الملفات

", unsafe_allow_html=True) # إنشاء تبويبات لمقارنة الملفات المختلفة tabs = st.tabs(["مقارنة المستندات", "مقارنة جداول البيانات", "مقارنة النصوص", "سجل المقارنات"]) with tabs[0]: self._render_document_comparison() with tabs[1]: self._render_spreadsheet_comparison() with tabs[2]: self._render_text_comparison() with tabs[3]: self._render_comparison_history() def _render_document_comparison(self): """ عرض واجهة مقارنة المستندات """ st.markdown("### مقارنة المستندات") st.markdown("مقارنة مستندات PDF أو Word مع إظهار الاختلافات بشكل مرئي") # رفع الملفات col1, col2 = st.columns(2) with col1: st.markdown("#### المستند الأول") file1 = st.file_uploader("اختر المستند الأول", type=["pdf", "docx"], key="doc_file1") with col2: st.markdown("#### المستند الثاني") file2 = st.file_uploader("اختر المستند الثاني", type=["pdf", "docx"], key="doc_file2") # خيارات المقارنة st.markdown("#### خيارات المقارنة") col1, col2, col3 = st.columns(3) with col1: st.checkbox("تجاهل التنسيق", value=False, key="ignore_formatting") with col2: st.checkbox("تجاهل الهوامش", value=True, key="ignore_headers_footers") with col3: st.checkbox("إظهار التغييرات الطفيفة", value=False, key="show_minor_changes") # زر المقارنة if st.button("مقارنة المستندات", key="compare_docs_btn"): if file1 is not None and file2 is not None: # محاكاة عملية المقارنة with st.spinner("جاري مقارنة المستندات..."): # محاكاة وقت المعالجة import time time.sleep(2) st.success("تمت مقارنة المستندات بنجاح!", icon="✅") # عرض ملخص المقارنة st.markdown("#### ملخص المقارنة") comparison_summary = { "عدد الصفحات المتطابقة": random.randint(3, 8), "عدد الصفحات المختلفة": random.randint(1, 5), "إجمالي التغييرات": random.randint(10, 50), "إضافات": random.randint(5, 20), "حذف": random.randint(5, 20), "تعديلات": random.randint(5, 20) } summary_df = pd.DataFrame({ "المعيار": list(comparison_summary.keys()), "القيمة": list(comparison_summary.values()) }) st.dataframe(summary_df, use_container_width=True, hide_index=True) # عرض صورة توضيحية للمقارنة st.markdown("#### معاينة المقارنة") st.info("سيتم عرض معاينة المقارنة هنا مع تمييز الاختلافات بألوان مختلفة", icon="ℹ️") # زر تنزيل تقرير المقارنة st.download_button( label="تنزيل تقرير المقارنة", data=b"محتوى وهمي لتقرير المقارنة", file_name="document_comparison_report.pdf", mime="application/pdf", key="download_doc_comparison" ) # إضافة المقارنة إلى السجل new_entry = { 'id': len(st.session_state.comparison_history) + 1, 'type': 'مستند', 'file1': file1.name, 'file2': file2.name, 'changes': comparison_summary["إجمالي التغييرات"], 'date': datetime.now().strftime("%Y-%m-%d %H:%M") } st.session_state.comparison_history.insert(0, new_entry) else: st.warning("يرجى رفع المستندين للمقارنة", icon="⚠️") def _render_spreadsheet_comparison(self): """ عرض واجهة مقارنة جداول البيانات """ st.markdown("### مقارنة جداول البيانات") st.markdown("مقارنة ملفات Excel أو CSV مع تحديد الاختلافات في البيانات") # رفع الملفات col1, col2 = st.columns(2) with col1: st.markdown("#### الجدول الأول") sheet1 = st.file_uploader("اختر الجدول الأول", type=["xlsx", "csv"], key="sheet_file1") with col2: st.markdown("#### الجدول الثاني") sheet2 = st.file_uploader("اختر الجدول الثاني", type=["xlsx", "csv"], key="sheet_file2") # خيارات المقارنة st.markdown("#### خيارات المقارنة") col1, col2 = st.columns(2) with col1: st.checkbox("مقارنة الصيغ", value=True, key="compare_formulas") st.checkbox("مقارنة التنسيق", value=False, key="compare_formatting") with col2: st.checkbox("تجاهل الأوراق المخفية", value=True, key="ignore_hidden_sheets") st.checkbox("مقارنة حسب القيمة فقط", value=False, key="compare_by_value") # زر المقارنة if st.button("مقارنة الجداول", key="compare_sheets_btn"): if sheet1 is not None and sheet2 is not None: # محاكاة عملية المقارنة with st.spinner("جاري مقارنة جداول البيانات..."): # محاكاة وقت المعالجة import time time.sleep(2) st.success("تمت مقارنة جداول البيانات بنجاح!", icon="✅") # عرض ملخص المقارنة st.markdown("#### ملخص المقارنة") comparison_summary = { "عدد الخلايا المتطابقة": random.randint(500, 2000), "عدد الخلايا المختلفة": random.randint(50, 200), "صفوف مضافة": random.randint(5, 20), "صفوف محذوفة": random.randint(5, 20), "أعمدة مضافة": random.randint(1, 5), "أعمدة محذوفة": random.randint(1, 5) } summary_df = pd.DataFrame({ "المعيار": list(comparison_summary.keys()), "القيمة": list(comparison_summary.values()) }) st.dataframe(summary_df, use_container_width=True, hide_index=True) # عرض جدول الاختلافات st.markdown("#### الاختلافات الرئيسية") # إنشاء بيانات تجريبية للاختلافات diff_data = [] for i in range(10): diff_data.append({ "الورقة": f"الورقة {random.randint(1, 3)}", "الخلية": f"{chr(65 + random.randint(0, 5))}{random.randint(1, 20)}", "القيمة الأولى": f"القيمة {i} (الأولى)", "القيمة الثانية": f"القيمة {i} (الثانية)", "نوع الاختلاف": random.choice(["تعديل", "إضافة", "حذف"]) }) diff_df = pd.DataFrame(diff_data) st.dataframe(diff_df, use_container_width=True) # زر تنزيل تقرير المقارنة st.download_button( label="تنزيل تقرير المقارنة", data=b"محتوى وهمي لتقرير المقارنة", file_name="spreadsheet_comparison_report.xlsx", mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", key="download_sheet_comparison" ) # إضافة المقارنة إلى السجل new_entry = { 'id': len(st.session_state.comparison_history) + 1, 'type': 'جدول بيانات', 'file1': sheet1.name, 'file2': sheet2.name, 'changes': comparison_summary["عدد الخلايا المختلفة"], 'date': datetime.now().strftime("%Y-%m-%d %H:%M") } st.session_state.comparison_history.insert(0, new_entry) else: st.warning("يرجى رفع جدولي البيانات للمقارنة", icon="⚠️") def _render_text_comparison(self): """ عرض واجهة مقارنة النصوص """ st.markdown("### مقارنة النصوص") st.markdown("مقارنة نصوص مباشرة أو ملفات نصية مع إظهار الاختلافات") # اختيار طريقة الإدخال input_method = st.radio( "طريقة الإدخال", options=["إدخال مباشر", "رفع ملفات"], horizontal=True, key="text_input_method" ) if input_method == "إدخال مباشر": # إدخال النصوص مباشرة col1, col2 = st.columns(2) with col1: st.markdown("#### النص الأول") text1 = st.text_area("أدخل النص الأول", height=200, key="direct_text1") with col2: st.markdown("#### النص الثاني") text2 = st.text_area("أدخل النص الثاني", height=200, key="direct_text2") # زر المقارنة if st.button("مقارنة النصوص", key="compare_direct_text_btn"): if text1 and text2: self._show_text_comparison_results(text1, text2) else: st.warning("يرجى إدخال النصين للمقارنة", icon="⚠️") else: # رفع ملفات نصية col1, col2 = st.columns(2) with col1: st.markdown("#### الملف الأول") text_file1 = st.file_uploader("اختر الملف الأول", type=["txt", "md", "json", "xml", "html", "css", "js", "py"], key="text_file1") with col2: st.markdown("#### الملف الثاني") text_file2 = st.file_uploader("اختر الملف الثاني", type=["txt", "md", "json", "xml", "html", "css", "js", "py"], key="text_file2") # زر المقارنة if st.button("مقارنة الملفات النصية", key="compare_text_files_btn"): if text_file1 is not None and text_file2 is not None: # قراءة محتوى الملفات text1 = text_file1.getvalue().decode("utf-8") text2 = text_file2.getvalue().decode("utf-8") self._show_text_comparison_results(text1, text2, text_file1.name, text_file2.name) else: st.warning("يرجى رفع الملفين النصيين للمقارنة", icon="⚠️") def _show_text_comparison_results(self, text1, text2, file1_name=None, file2_name=None): """ عرض نتائج مقارنة النصوص """ # محاكاة عملية المقارنة with st.spinner("جاري مقارنة النصوص..."): # استخدام difflib للمقارنة d = difflib.Differ() diff = list(d.compare(text1.splitlines(), text2.splitlines())) # عرض ملخص المقارنة st.markdown("#### ملخص المقارنة") # حساب الإحصائيات added = len([line for line in diff if line.startswith('+ ')]) removed = len([line for line in diff if line.startswith('- ')]) changed = len([line for line in diff if line.startswith('? ')]) unchanged = len([line for line in diff if line.startswith(' ')]) comparison_summary = { "الأسطر المتطابقة": unchanged, "الأسطر المضافة": added, "الأسطر المحذوفة": removed, "الأسطر المتغيرة": changed, "إجمالي الاختلافات": added + removed + changed } summary_df = pd.DataFrame({ "المعيار": list(comparison_summary.keys()), "القيمة": list(comparison_summary.values()) }) st.dataframe(summary_df, use_container_width=True, hide_index=True) # عرض الاختلافات st.markdown("#### عرض الاختلافات") # تنسيق الاختلافات بألوان مختلفة html_diff = [] for line in diff: if line.startswith('+ '): html_diff.append(f'
{line}
') elif line.startswith('- '): html_diff.append(f'
{line}
') elif line.startswith('? '): html_diff.append(f'
{line}
') else: html_diff.append(f'
{line}
') st.markdown(''.join(html_diff), unsafe_allow_html=True) # زر تنزيل تقرير المقارنة st.download_button( label="تنزيل تقرير المقارنة", data='\n'.join(diff), file_name="text_comparison_report.txt", mime="text/plain", key="download_text_comparison" ) # إضافة المقارنة إلى السجل new_entry = { 'id': len(st.session_state.comparison_history) + 1, 'type': 'نص', 'file1': file1_name or "نص مباشر 1", 'file2': file2_name or "نص مباشر 2", 'changes': comparison_summary["إجمالي الاختلافات"], 'date': datetime.now().strftime("%Y-%m-%d %H:%M") } st.session_state.comparison_history.insert(0, new_entry) def _render_comparison_history(self): """ عرض سجل المقارنات """ st.markdown("### سجل المقارنات") st.markdown("عرض سجل المقارنات السابقة مع إمكانية البحث والتصفية") # خيارات التصفية col1, col2 = st.columns(2) with col1: filter_type = st.multiselect( "نوع المقارنة", options=["الكل", "مستند", "جدول بيانات", "نص"], default=["الكل"] ) with col2: date_range = st.selectbox( "النطاق الزمني", options=["الكل", "اليوم", "الأسبوع الماضي", "الشهر الماضي"] ) # تطبيق التصفية filtered_history = st.session_state.comparison_history if "الكل" not in filter_type: filtered_history = [h for h in filtered_history if h['type'] in filter_type] # تحويل البيانات إلى DataFrame if filtered_history: df = pd.DataFrame(filtered_history) df = df[['date', 'type', 'file1', 'file2', 'changes']] df.columns = ['التاريخ', 'النوع', 'الملف الأول', 'الملف الثاني', 'عدد الاختلافات'] # عرض الجدول st.dataframe(df, use_container_width=True) else: st.info("لا توجد مقارنات تطابق معايير التصفية", icon="ℹ️") def _generate_sample_history(self): """ إنشاء بيانات تجريبية لسجل المقارنات """ comparison_types = ['مستند', 'جدول بيانات', 'نص'] file_names = { 'مستند': [ 'مواصفات_المشروع_v1.pdf', 'مواصفات_المشروع_v2.pdf', 'العقد_النهائي.docx', 'العقد_المعدل.docx', 'تقرير_المشروع_2025.pdf', 'تقرير_المشروع_2025_مراجعة.pdf' ], 'جدول بيانات': [ 'جدول_الكميات_v1.xlsx', 'جدول_الكميات_v2.xlsx', 'تحليل_الأسعار_2025.xlsx', 'تحليل_الأسعار_2025_محدث.xlsx', 'الميزانية_التقديرية.xlsx', 'الميزانية_النهائية.xlsx' ], 'نص': [ 'ملاحظات_الاجتماع.txt', 'ملاحظات_الاجتماع_محدثة.txt', 'شروط_المناقصة.txt', 'شروط_المناقصة_معدلة.txt', 'config.json', 'config_new.json' ] } history = [] for i in range(15): comp_type = random.choice(comparison_types) # اختيار ملفين من نفس النوع file_index = random.randint(0, 2) * 2 file1 = file_names[comp_type][file_index] file2 = file_names[comp_type][file_index + 1] # تحديد تاريخ عشوائي خلال الشهر الماضي days_ago = random.randint(0, 30) entry_date = (datetime.now() - pd.Timedelta(days=days_ago)).strftime("%Y-%m-%d %H:%M") entry = { 'id': i + 1, 'type': comp_type, 'file1': file1, 'file2': file2, 'changes': random.randint(10, 100), 'date': entry_date } history.append(entry) # ترتيب السجل حسب التاريخ (الأحدث أولاً) history.sort(key=lambda x: x['date'], reverse=True) return history