| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- #include "pch.h"
- #include "CCaigouPageUI.h"
- #include "../control/ControlEx.h"
- #include "../wnd/CMainWnd.h"
- #include "../wnd/CKucunQtyGuardWnd.h"
- namespace
- {
- // 从被点的子控件回溯到 ListContainerElement,读 col_no 标签拿采购单号
- std::wstring CgRowNo(CControlUI* p)
- {
- while (p != NULL)
- {
- CListContainerElementUI* row = dynamic_cast<CListContainerElementUI*>(p);
- if (row != NULL)
- {
- CLabelUI* lab = static_cast<CLabelUI*>(row->FindSubControl(L"col_no"));
- if (lab != NULL) return std::wstring((LPCTSTR)lab->GetText());
- return L"";
- }
- p = p->GetParent();
- }
- return L"";
- }
- }
- CCaigouPageUI::CCaigouPageUI()
- : m_pMain(NULL), m_pNew(NULL), m_pKpHost(NULL), m_pPickOverlay(NULL), m_pPickList(NULL),
- m_nPickCat(0), m_nSubView(-1), m_nPeriod(0), m_nPageWidth(0)
- {
- // 弹层候选项来自商品档案,勾选态(on)跨分类保留
- const std::vector<KcGoods>& all = KcAllGoods();
- for (size_t i = 0; i < all.size(); i++)
- {
- CgPickItem it;
- it.name = all[i].name;
- it.cat = all[i].cat;
- it.unit = all[i].unit;
- it.stock = all[i].stock;
- it.on = false;
- m_pick.push_back(it);
- }
- }
- CCaigouPageUI::~CCaigouPageUI()
- {
- if (m_pMain) { delete m_pMain; m_pMain = NULL; }
- if (m_pNew) { delete m_pNew; m_pNew = NULL; }
- }
- void CCaigouPageUI::InitControl()
- {
- CPaintManagerUI* pm = GetManager();
- // 主态视图(记录 + 统计 双卡,host = cg_scroll)
- CContainerUI* hMain = static_cast<CContainerUI*>(FindSubControl(L"cg_scroll"));
- m_pMain = new CCaigouMainView(pm, hMain);
- m_pMain->OnInitControl();
- // 新建采购单子视图(host = cg_view_order_new,键盘 host = cg_keypad)
- m_pKpHost = static_cast<CContainerUI*>(FindSubControl(L"cg_keypad"));
- CContainerUI* hNew = static_cast<CContainerUI*>(FindSubControl(L"cg_view_order_new"));
- m_pNew = new CCaigouNewView(pm, hNew, m_pKpHost);
- m_pNew->OnInitControl();
- // 添加商品弹层
- m_pPickOverlay = static_cast<CContainerUI*>(FindSubControl(L"cg_pick_overlay"));
- m_pPickList = static_cast<CListUI*>(FindSubControl(L"cg_pick_list"));
- ShowMain();
- }
- void CCaigouPageUI::InitShow()
- {
- ShowMain();
- if (m_pMain) m_pMain->InitShow();
- SyncPeriodSeg();
- }
- // ---------------------------------------------------------------- 视图显隐
- void CCaigouPageUI::ShowMain()
- {
- CControlUI* pScroll = FindSubControl(L"cg_scroll");
- if (pScroll) pScroll->SetVisible(true);
- CControlUI* pNew = FindSubControl(L"cg_view_order_new");
- if (pNew) pNew->SetVisible(false);
- CControlUI* pFoot = FindSubControl(L"cg_new_foot");
- if (pFoot) pFoot->SetVisible(false);
- if (m_pKpHost) m_pKpHost->SetVisible(false);
- if (m_pPickOverlay) m_pPickOverlay->SetVisible(false);
- if (m_pNew) m_pNew->CloseKeypad();
- m_nSubView = -1;
- KcSyncNativeEditsIn(this);
- }
- void CCaigouPageUI::ShowSubView(int idx)
- {
- if (idx != 0 || m_pNew == NULL) return;
- CControlUI* pScroll = FindSubControl(L"cg_scroll");
- if (pScroll) pScroll->SetVisible(false);
- CControlUI* pNew = FindSubControl(L"cg_view_order_new");
- if (pNew) pNew->SetVisible(true);
- CControlUI* pFoot = FindSubControl(L"cg_new_foot");
- if (pFoot) pFoot->SetVisible(true);
- if (m_pKpHost) m_pKpHost->SetVisible(false);
- if (m_pPickOverlay) m_pPickOverlay->SetVisible(false);
- m_nSubView = 0;
- m_pNew->InitShow();
- KcSyncNativeEditsIn(this);
- }
- void CCaigouPageUI::SyncPeriodSeg()
- {
- for (int i = 0; i < 3; i++)
- {
- LPCTSTR nm[3] = { L"cg_per_0", L"cg_per_1", L"cg_per_2" };
- CCaigouViewBase::StylePeriodSeg(
- static_cast<CButtonUI*>(FindSubControl(nm[i])), i == m_nPeriod);
- }
- CControlUI* pRange = FindSubControl(L"cg_per_range");
- // ⭐【R75】cg_per_range 是 autocalcwidth(区间文案长度按周期变)⇒ 走 SetLabelText,
- // 只 SetText 会被按旧宽度裁掉。口径与视图侧 CCaigouMainView::SetPeriod 一致。
- if (pRange != NULL && m_pMain != NULL)
- CCaigouViewBase::SetLabelText(pRange, CgPeriodRangeText(m_nPeriod).c_str());
- }
- // ---------------------------------------------------------------- 添加商品弹层
- void CCaigouPageUI::ShowPick(bool bShow)
- {
- if (m_pPickOverlay == NULL) return;
- if (bShow)
- {
- if (m_pNew) m_pNew->CloseKeypad();
- for (size_t i = 0; i < m_pick.size(); i++) m_pick[i].on = false;
- m_strPickSearch.clear();
- CEditUI* pSearch = static_cast<CEditUI*>(FindSubControl(L"cg_pick_search"));
- if (pSearch) pSearch->SetText(L"");
- PickSetCat(0);
- }
- m_pPickOverlay->SetVisible(bShow);
- KcSyncNativeEditsIn(this);
- }
- void CCaigouPageUI::PickSetCat(int idx)
- {
- if (idx < 0 || idx > 6) idx = 0;
- m_nPickCat = idx;
- for (int i = 0; i < 7; i++)
- {
- CButtonUI* p = static_cast<CButtonUI*>(FindSubControl(
- (std::wstring(L"cg_pick_cat_") + std::to_wstring(i)).c_str()));
- if (p == NULL) continue;
- bool act = (i == idx);
- p->SetNormalImage(act ? L"file='dc_pill_h.png' corner='11,11,11,11'" : L"");
- p->SetTextColor(act ? 0xFF2E9B5C : 0xFF5F6368);
- p->SetHotTextColor(0xFF2E9B5C);
- p->SetPushedTextColor(0xFF1B8A4C);
- p->SetFont(act ? 113 : 13);
- }
- RefreshPickList();
- }
- void CCaigouPageUI::RefreshPickList()
- {
- if (m_pPickList == NULL) return;
- while (m_pPickList->GetCount() > 0) m_pPickList->RemoveAt(0);
- m_pickView.clear();
- std::wstring kw = m_strPickSearch;
- for (int i = 0; i < (int)m_pick.size(); i++)
- {
- const CgPickItem& it = m_pick[i];
- if (m_nPickCat > 0 && CG_CATS[m_nPickCat] != it.cat) continue;
- if (!kw.empty())
- {
- KcGoods g;
- std::wstring py = KcLookupGoods(it.name, g) ? g.py : L"";
- if (it.name.find(kw) == std::wstring::npos &&
- py.find(kw) == std::wstring::npos) continue;
- }
- CDialogBuilder builder;
- CDialogBuilderCallbackEx cb;
- CListContainerElementUI* row =
- static_cast<CListContainerElementUI*>(builder.Create(L"cg_row_pick.xml", (UINT)0, &cb, GetManager()));
- if (row == NULL) continue;
- CLabelUI* pName = static_cast<CLabelUI*>(row->FindSubControl(L"pk_name"));
- CLabelUI* pMeta = static_cast<CLabelUI*>(row->FindSubControl(L"pk_meta"));
- CLabelUI* pStock = static_cast<CLabelUI*>(row->FindSubControl(L"pk_stock"));
- CControlUI* pCb = row->FindSubControl(L"pk_cb");
- if (pName) pName->SetText(it.name.c_str());
- if (pMeta) pMeta->SetText((it.cat + L" · " + it.unit).c_str());
- if (pStock) pStock->SetText(std::to_wstring(it.stock).c_str());
- if (pCb) pCb->SetBkImage(it.on ? L"kc_chk_on_24.png" : L"kc_chk_off_24.png");
- m_pPickList->Add(row);
- m_pickView.push_back(i);
- }
- SyncPickSelCnt();
- }
- void CCaigouPageUI::TogglePickRow(int idx)
- {
- if (idx < 0 || idx >= (int)m_pickView.size()) return;
- int gi = m_pickView[idx];
- m_pick[gi].on = !m_pick[gi].on;
- CListContainerElementUI* row =
- static_cast<CListContainerElementUI*>(m_pPickList->GetItemAt(idx));
- if (row != NULL)
- {
- CControlUI* pCb = row->FindSubControl(L"pk_cb");
- if (pCb) pCb->SetBkImage(m_pick[gi].on ? L"kc_chk_on_24.png" : L"kc_chk_off_24.png");
- }
- SyncPickSelCnt();
- }
- void CCaigouPageUI::SyncPickSelCnt()
- {
- int n = 0;
- for (size_t i = 0; i < m_pick.size(); i++) if (m_pick[i].on) n++;
- CLabelUI* p = static_cast<CLabelUI*>(FindSubControl(L"cg_pick_selcnt"));
- // ⭐【R75】cg_pick_selcnt 是 autocalcwidth(「已选 3 项」→「已选 12 项」位数会变)
- // ⇒ 走 SetLabelText,只 SetText 会被按旧宽度裁掉。
- if (p != NULL)
- CCaigouViewBase::SetLabelText(p, (L"已选 " + std::to_wstring(n) + L" 项").c_str());
- }
- std::vector<std::wstring> CCaigouPageUI::CollectPicked() const
- {
- std::vector<std::wstring> out;
- for (size_t i = 0; i < m_pick.size(); i++)
- if (m_pick[i].on) out.push_back(m_pick[i].name);
- return out;
- }
- void CCaigouPageUI::AppendPickedFromOverlay()
- {
- std::vector<std::wstring> picked = CollectPicked();
- if (m_pNew) m_pNew->AppendPicked(picked);
- ShowPick(false);
- }
- // ---------------------------------------------------------------- 详情弹框
- void CCaigouPageUI::OpenDetail(const CgDocDetail& doc)
- {
- if (m_is_show_modal_wnd) return;
- CCaigouDetailWnd* pDlg = new CCaigouDetailWnd(doc);
- m_is_show_modal_wnd = true;
- m_curModalWnd = pDlg;
- pDlg->Create(GetManager()->GetPaintWindow(), _T(""), UI_WNDSTYLE_DIALOG, WS_EX_WINDOWEDGE);
- pDlg->SetIcon(IDI_ICON_DUILIB);
- pDlg->LoadDetail();
- if (m_pMainWnd != NULL) m_pMainWnd->ShowGlobalDim(true);
- pDlg->CenterWindow();
- pDlg->ShowModal();
- if (m_pMainWnd != NULL) m_pMainWnd->ShowGlobalDim(false);
- m_is_show_modal_wnd = false;
- m_curModalWnd = NULL;
- const bool bPrint = pDlg->IsPrintClicked();
- delete pDlg;
- if (bPrint && m_pMainWnd != NULL)
- m_pMainWnd->ShowToast(L"打印小票:热敏小票本轮未接入");
- }
- // ---------------------------------------------------------------- 事件路由
- void CCaigouPageUI::HandleClickMsg(TNotifyUI& msg)
- {
- std::wstring n = (LPCTSTR)msg.pSender->GetName();
- // 主态「新建采购单」按钮 → 进子视图
- if (n == L"cg_rec_new_btn" || n == L"cg_stat_new_btn") { ShowSubView(0); return; }
- // ---- 添加商品弹层(必须在子视图分支【之前】判定!)
- // 弹层正是从「新建采购单」页点「添加商品」打开的,此时 m_nSubView==0。
- // 若把弹层判定放到子视图分支之后,弹层内任何点击都会先落进
- // `if (m_nSubView == 0)` 那段被整段吞掉、转发给 m_pNew->OnClick
- // ⇒ 弹层里的行 / 分类 / 清空 / 取消 / 确定 全部点不动。
- // 判定顺序与库存页 CKucunPageUI::HandleClickMsg 保持一致。
- if (n == L"pk_row")
- {
- int idx = (m_pPickList != NULL) ? m_pPickList->GetItemIndex(msg.pSender) : -1;
- TogglePickRow(idx);
- return;
- }
- if (n == L"cg_pick_close" || n == L"cg_pick_cancel") { ShowPick(false); return; }
- if (n == L"cg_pick_clear")
- {
- for (size_t i = 0; i < m_pick.size(); i++) m_pick[i].on = false;
- RefreshPickList();
- return;
- }
- if (n == L"cg_pick_ok") { AppendPickedFromOverlay(); return; }
- if (n.size() > 12 && n.compare(0, 12, L"cg_pick_cat_") == 0)
- {
- PickSetCat(_wtoi(n.c_str() + 12));
- return;
- }
- // 新建态页面级按钮
- if (m_nSubView == 0)
- {
- if (n == L"cg_cgn_back" || n == L"cg_cgn_cancel") { ShowMain(); return; }
- if (n == L"cg_cgn_save")
- {
- // 【R74】保存 / 提交前的采购数量校验,口径与库存页入库 / 出库**完全一致**:
- // 键盘清空即归 0、「不存在空」⇒ 0(含未录入)只能是漏填,硬拦不让走。
- // 明细单元格边框早已按「编辑绿 / 0 琥珀 / 常态白」着色(ApplyCellStyle),
- // 这里只负责把问题行摆到弹框里让用户看清是第几行、哪一项。
- // 采购页只有一张明细表,无盘点语义 ⇒ kind 恒为 0、允许「删除该行」。
- if (m_pNew != NULL)
- {
- std::vector<KcQtyIssue> issues;
- m_pNew->CollectQtyIssues(issues);
- if (!issues.empty())
- {
- // 逐行报「商品名 + 行号」:合计条只给项数,不报行号用户定位不到是哪一行。
- // 弹框自己会截断到 8 行并追加「…等共 N 项」,这里不截。
- std::vector<std::wstring> lines;
- for (size_t i = 0; i < issues.size(); i++)
- {
- wchar_t b[256];
- swprintf_s(b, L"%s(第 %d 行)· %s%s",
- issues[i].name.c_str(), issues[i].row + 1,
- issues[i].field.c_str(),
- issues[i].unfilled ? L"未录入" : L"为 0");
- lines.push_back(b);
- }
- // 「删除该行」只在**单行**出错时给 —— 多行时删哪一行有歧义。
- bool bAllowDel = (issues.size() == 1);
- CKucunQtyGuardWnd* pDlg = new CKucunQtyGuardWnd(0, lines, bAllowDel);
- m_is_show_modal_wnd = true;
- m_curModalWnd = pDlg;
- pDlg->Create(GetManager()->GetPaintWindow(), _T(""), UI_WNDSTYLE_DIALOG, WS_EX_WINDOWEDGE);
- pDlg->SetIcon(IDI_ICON_DUILIB);
- pDlg->Load(); // 铺文案 + 按清单行数调窗高
- if (m_pMainWnd != NULL) m_pMainWnd->ShowGlobalDim(true);
- pDlg->CenterWindow();
- pDlg->ShowModal();
- if (m_pMainWnd != NULL) m_pMainWnd->ShowGlobalDim(false);
- m_is_show_modal_wnd = false;
- m_curModalWnd = NULL;
- // 单行出错才点了就有反应(bAllowDel 已经保证多行时那枚按钮根本不显示,
- // 这里再判一次 size()==1 是防呆):把它从明细里删掉,页面停在原处接着改。
- bool bDel = pDlg->IsDeleteClicked();
- delete pDlg;
- if (bDel && issues.size() == 1) m_pNew->DeleteLine(issues[0].row);
- return; // 硬拦:不保存、也不 leave 本页
- }
- }
- if (m_pMainWnd != NULL) m_pMainWnd->ShowToast(L"采购单已提交(占位,后端未接入)");
- return;
- }
- if (n == L"cg_cgn_add") { ShowPick(true); return; }
- // 其余(明细行按钮、数字键盘)交给新建视图
- if (m_pNew) m_pNew->OnClick(msg);
- return;
- }
- // 记录行详情 / 打印
- if (n == L"op_detail")
- {
- std::wstring no = CgRowNo(msg.pSender);
- CgDocDetail d;
- if (!CgLookupDetail(no, d))
- {
- if (m_pMainWnd != NULL) m_pMainWnd->ShowToast(L"未找到单据详情:" + no);
- return;
- }
- OpenDetail(d);
- return;
- }
- if (n == L"op_print")
- {
- std::wstring no = CgRowNo(msg.pSender);
- if (m_pMainWnd != NULL)
- m_pMainWnd->ShowToast(L"打印(占位):" + (no.empty() ? std::wstring(L"未取到单号") : no));
- return;
- }
- // 其余交给主态视图
- if (m_pMain) m_pMain->OnClick(msg);
- }
- void CCaigouPageUI::HandleSelectChangeMsg(TNotifyUI& msg)
- {
- // 采购页无 Option / CheckBox;弹层勾选方块是 Control,靠整行 itemclick 切换
- (void)msg;
- }
- void CCaigouPageUI::HandleItemSelectMsg(TNotifyUI& msg)
- {
- if (m_pMain) m_pMain->OnItemSelect(msg);
- }
- void CCaigouPageUI::HandleTextChangedMsg(TNotifyUI& msg)
- {
- std::wstring n = (LPCTSTR)msg.pSender->GetName();
- if (n == L"cg_pick_search")
- {
- CEditUI* pEdit = static_cast<CEditUI*>(msg.pSender);
- if (pEdit) m_strPickSearch = (LPCTSTR)pEdit->GetText();
- RefreshPickList();
- return;
- }
- if (m_pMain) m_pMain->OnTextChanged(msg);
- }
- void CCaigouPageUI::HandleReturnMsg(TNotifyUI& msg)
- {
- if (m_pMain) m_pMain->SubmitSearch();
- (void)msg;
- }
- void CCaigouPageUI::HandleTextCapture(std::string content)
- {
- // 扫码枪:本轮不接后端,留空(将来可在新建态按条码追加商品)
- (void)content;
- }
- bool CCaigouPageUI::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- // 采购页无自定义窗口消息需要处理
- (void)uMsg; (void)wParam; (void)lParam;
- return false;
- }
- void CCaigouPageUI::SetPos(RECT rc, bool bNeedInvalidate)
- {
- m_nPageWidth = rc.right - rc.left;
- CContainerUI::SetPos(rc, bNeedInvalidate);
- }
|