From de5797378e67b1f17091ad63f017f63de62e9559 Mon Sep 17 00:00:00 2001 From: DXC Date: Mon, 19 Jan 2026 12:47:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=89=88=E7=BB=88=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- new_页面内容.py | 75 +++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/new_页面内容.py b/new_页面内容.py index a7e7da5..06c7e47 100644 --- a/new_页面内容.py +++ b/new_页面内容.py @@ -6,7 +6,7 @@ import re import urllib.parse import webbrowser import json -from datetime import datetime +from datetime import datetime, timedelta import tkinter as tk from tkinter import filedialog, messagebox @@ -14,18 +14,23 @@ import requests import pandas as pd from lxml import html -# ================= 1. 导入 UI 库 ================= +# ================= 1. 导入 UI 库 (已修正路径) ================= import ttkbootstrap as ttk from ttkbootstrap.constants import * from ttkbootstrap.dialogs import Messagebox -# 兼容导入 +# 修正后的组件导入 try: - from ttkbootstrap.widgets import ScrolledText, Tableview, ToastNotification -except ImportError: + from ttkbootstrap.widgets import DateEntry from ttkbootstrap.scrolled import ScrolledText from ttkbootstrap.tableview import Tableview from ttkbootstrap.toast import ToastNotification +except ImportError: + # 兼容性导入 + from ttkbootstrap.widgets import DateEntry + from tkinter.scrolledtext import ScrolledText + from ttkbootstrap.tableview import Tableview + from ttkbootstrap.toast import ToastNotification # ================= 2. 后端核心逻辑 ================= @@ -65,7 +70,6 @@ class CRMCrawler: return int(time.time() * 1000) def clean_num(self, val): - """将 1.0000 转换为 1,保留必要的小数,为空则返回空字符串""" if val is None or val == "": return "" try: f_val = float(val) @@ -83,12 +87,6 @@ class CRMCrawler: return 0.0 def fetch_product_details(self, record_id, contract_no, sales_person, outsourced_desc_from_html): - """ - 修正后的价格逻辑: - 1. 销售单价/销售总价 -> 永远不填 (代码中置空) - 2. 厂家是"外购" -> 报价单价/总价置空,总金额填入"外购"列 - 3. 厂家非"外购" -> 金额填入报价单价/总价,"外购"列置空 - """ detail_payload = { "module": "Plugins", "pluginName": "DetailProductTable", "action": "getTableData", "moduleName": "SalesOrder", "record": record_id, "actionId": self.get_timestamp(), "isTool": "1" @@ -114,7 +112,6 @@ class CRMCrawler: products.append(v) for prod in products: - # 1. 基础信息 manufacturer = self._get_nested_val(prod, 'cf_2128') or self._get_nested_val(prod, 'manufacturer') prod_desc_text = prod.get('productname', '') unit = self._get_nested_val(prod, 'usageunit') @@ -122,23 +119,19 @@ class CRMCrawler: discount = self.clean_num(self._get_nested_val(prod, 'discount_percent')) currency = self._get_nested_val(prod, 'cf_534') - # 2. 价格获取 list_price_raw = self._get_nested_val(prod, 'listPrice') f_qty = self._safe_float(qty_raw) f_list_price = self._safe_float(list_price_raw) - f_total_val = f_list_price * f_qty # 计算总价 + f_total_val = f_list_price * f_qty - # 3. 判断外购逻辑 is_outsourced = False if manufacturer and "外购" in manufacturer: is_outsourced = True - # 4. 处理产品描述 final_desc = prod_desc_text if is_outsourced and outsourced_desc_from_html: final_desc = outsourced_desc_from_html - # 5. 分配金额到指定列 col_quote_unit = "" col_quote_total = "" col_sales_unit = "" @@ -146,14 +139,11 @@ class CRMCrawler: col_outsourced = "" if is_outsourced: - # 外购:报价列为空,金额填入外购列(总价) col_outsourced = self.clean_num(f_total_val) else: - # 非外购:金额填入报价列,外购列为空 col_quote_unit = self.clean_num(f_list_price) col_quote_total = self.clean_num(f_total_val) - # 构建行数据 row = { "合同编号": contract_no, "销售员": sales_person, @@ -165,11 +155,10 @@ class CRMCrawler: "币种": currency, "报价单价": col_quote_unit, "报价总价": col_quote_total, - "销售单价": col_sales_unit, # 留空 - "销售总价": col_sales_total, # 留空 + "销售单价": col_sales_unit, + "销售总价": col_sales_total, "折扣率": discount, "外购": col_outsourced, - # 预留列 "合同币种/美元": "", "外购转美元": "", "报价总价美元": "", @@ -429,15 +418,18 @@ class CRMGUI(ttk.Window): self.nb_mode = ttk.Notebook(mode_grp, bootstyle="primary") self.nb_mode.pack(fill=BOTH, expand=True) + # === 📅 日期选择部分 === f_date = ttk.Frame(self.nb_mode, padding=10) self.nb_mode.add(f_date, text="📅 按时间范围") - self.ent_start = ttk.Entry(f_date, width=12); - self.ent_start.insert(0, "2026-01-14"); + + self.ent_start = DateEntry(f_date, dateformat='%Y-%m-%d', width=11, bootstyle="primary") self.ent_start.pack(side=LEFT, padx=5) + ttk.Label(f_date, text="至").pack(side=LEFT) - self.ent_end = ttk.Entry(f_date, width=12); - self.ent_end.insert(0, "2026-01-15"); + + self.ent_end = DateEntry(f_date, dateformat='%Y-%m-%d', width=11, bootstyle="primary") self.ent_end.pack(side=LEFT, padx=5) + # ========================= f_search = ttk.Frame(self.nb_mode, padding=10) self.nb_mode.add(f_search, text="🔍 关键词搜索") @@ -527,7 +519,6 @@ class CRMGUI(ttk.Window): tv.pack(side=LEFT, fill=BOTH, expand=True) for c in cols: - # === 全居中设置 === tv.heading(c, text=c, anchor="center") w = 100 if "描述" in c or "标的" in c or "公司" in c or "单位" in c: @@ -540,7 +531,6 @@ class CRMGUI(ttk.Window): w = 80 tv.column(c, width=w, minwidth=50, anchor="center") - # 移除双击编辑,保留右键菜单(仅用于浏览器打开) tv.bind("", lambda e: self.on_right_click(e, tv, key)) self.treeviews[key] = tv @@ -587,13 +577,14 @@ class CRMGUI(ttk.Window): kwargs = {} if curr_idx == 0: mode = "date" - kwargs = {'start': self.ent_start.get(), 'end': self.ent_end.get()} + kwargs = {'start': self.ent_start.entry.get(), 'end': self.ent_end.entry.get()} elif curr_idx == 1: mode = "search" kwargs = {'query': self.ent_query.get()} try: - self.crawler.run_task(mode, **kwargs); self.log_msg("🎉 完成!") + self.crawler.run_task(mode, **kwargs); + self.log_msg("🎉 完成!") except Exception as e: self.log_msg(f"❌ 错误: {e}") finally: @@ -626,7 +617,6 @@ class CRMGUI(ttk.Window): self.stored_data[main_key][sub_key].append(record) record_idx = len(self.stored_data[main_key][sub_key]) - 1 - # 主表 tv_key = f"{main_key}_{sub_key}" tv = self.treeviews.get(tv_key) if tv: @@ -634,7 +624,6 @@ class CRMGUI(ttk.Window): vals = [record.get(c, "") for c in cols] tv.insert("", END, iid=f"main_{main_key}_{sub_key}_{record_idx}", values=vals) - # 明细表 detail_key_suffix = "" if sub_key == "Domestic": detail_key_suffix = "Domestic" @@ -659,7 +648,6 @@ class CRMGUI(ttk.Window): if not item_id: return tv.selection_set(item_id) - # 仅在主表行点击时提供浏览器打开功能 if item_id.startswith("main_"): parts = item_id.split('_') main_key, sub_key, idx = parts[1], parts[2], int(parts[3]) @@ -675,7 +663,6 @@ class CRMGUI(ttk.Window): url = f"http://111.198.24.44:88/index.php?module=SalesOrder&action=DetailView&record={crm_id}" webbrowser.open(url) - # --- 导出功能 --- def export_data(self): folder = filedialog.askdirectory() if not folder: return @@ -709,6 +696,11 @@ class CRMGUI(ttk.Window): else: detail_domestic_rows.extend(products) + # ========== 核心修改:按合同编号升序排列 ========== + detail_domestic_rows.sort(key=lambda x: x.get("合同编号", "")) + detail_foreign_rows.sort(key=lambda x: x.get("合同编号", "")) + # =============================================== + path = os.path.join(folder, f"{prefix}_{ts}.xlsx") try: with pd.ExcelWriter(path, engine='openpyxl') as writer: @@ -718,6 +710,9 @@ class CRMGUI(ttk.Window): if c not in df.columns: df[c] = "" cols = export_cols[:2] + ["内贸合同号"] + export_cols[2:] df = df.reindex(columns=cols) + + # --- 排序 --- + df.sort_values(by="合同编号", ascending=True, inplace=True) df.to_excel(writer, sheet_name='内贸汇总', index=False) if data_map['Foreign']: @@ -726,6 +721,9 @@ class CRMGUI(ttk.Window): if c not in df.columns: df[c] = "" cols = export_cols[:2] + ["外贸合同号"] + export_cols[2:] df = df.reindex(columns=cols) + + # --- 排序 --- + df.sort_values(by="合同编号", ascending=True, inplace=True) df.to_excel(writer, sheet_name='外贸汇总', index=False) if data_map['Other']: @@ -734,16 +732,21 @@ class CRMGUI(ttk.Window): if c not in df.columns: df[c] = "" cols = export_cols[:2] + ["内贸合同号"] + export_cols[2:] df = df.reindex(columns=cols) + + # --- 排序 --- + df.sort_values(by="合同编号", ascending=True, inplace=True) df.to_excel(writer, sheet_name='其他汇总', index=False) if detail_domestic_rows: df_d = pd.DataFrame(detail_domestic_rows) df_d = df_d.reindex(columns=detail_cols_order) + # (已在前面 List 阶段排序) df_d.to_excel(writer, sheet_name='内贸明细', index=False) if detail_foreign_rows: df_f = pd.DataFrame(detail_foreign_rows) df_f = df_f.reindex(columns=detail_cols_order) + # (已在前面 List 阶段排序) df_f.to_excel(writer, sheet_name='外贸明细', index=False) self.log_msg(f" ✅ 导出成功: {os.path.basename(path)}")