diff --git a/client/lib/screens/finance/finance_screen.dart b/client/lib/screens/finance/finance_screen.dart index b5a22fe..ce1ad9f 100644 --- a/client/lib/screens/finance/finance_screen.dart +++ b/client/lib/screens/finance/finance_screen.dart @@ -63,7 +63,8 @@ class _FinanceScreenState extends ConsumerState { String _summaryKw = ''; // 桌面汇总表表头「往来单位」下拉筛选(验收反馈改版:由卡标题行文字搜索 // 改为表头内嵌 ComboSearchField,同 _flowTable 往来单位筛选控件;单选精确 - // 匹配一行,× 清除恢复全量;候选=当前汇总行往来单位,口径=显示口径)。 + // 匹配一行,× 清除恢复全量;候选=全量往来单位(allPartnersProvider,与 + // _flowTable toolbar 同源),选中一个汇总里没有行的单位时显示空态)。 int? _summaryPartnerId; static const _flowChips = ['全部', '应收', '应付', '收款', '付款']; @@ -111,8 +112,7 @@ class _FinanceScreenState extends ConsumerState { case '自定义': final picked = await showDateRangeDropdown( anchorContext, - initial: - _customRange ?? + initial: _customRange ?? DateTimeRange(start: DateTime(now.year, now.month, 1), end: now), ); if (picked == null) return; @@ -575,15 +575,15 @@ class _FinanceScreenState extends ConsumerState { final t = context.tokens; final trend = ref.watch(financeTrendProvider); Widget placeholder(Widget child) => Container( - height: 120, - alignment: Alignment.center, - decoration: BoxDecoration( - color: t.surface, - border: Border.all(color: t.border), - borderRadius: BorderRadius.circular(AppDims.rLg), - ), - child: child, - ); + height: 120, + alignment: Alignment.center, + decoration: BoxDecoration( + color: t.surface, + border: Border.all(color: t.border), + borderRadius: BorderRadius.circular(AppDims.rLg), + ), + child: child, + ); return trend.when( loading: () => placeholder( const SizedBox( @@ -640,19 +640,17 @@ class _FinanceScreenState extends ConsumerState { ), data: (allRows) { final rows = _filterSummaryByPartner(allRows); - // 下拉候选=当前汇总行往来单位(口径=显示口径,不用全量 partners,避免 - // 选到无余额单位出空表);id 合成规则同 _filterSummaryByPartner。 - final partnerOptions = [ - for (var i = 0; i < allRows.length; i++) - OptionItem( - id: allRows[i].partnerId ?? -(i + 1), - name: allRows[i].name, - ), - ]; + // 下拉候选=全量往来单位(验收反馈:与 _flowTable toolbar 往来单位筛选 + // 同源 allPartnersProvider,而非只列汇总行里出现的单位);选中一个汇总 + // 无余额的单位时,_filterSummaryByPartner 匹配不到行会返回空列表, + // 走既有「没有匹配的往来单位」空态。 + final partnerOptions = + (ref.watch(allPartnersProvider).valueOrNull?.data ?? const []) + .map((p) => OptionItem(id: p.id, name: p.name, code: p.code)) + .toList(); return DsTable( shrinkWrap: true, - emptyText: - _summaryPartnerId == null ? '暂无未结清的应收 / 应付' : '没有匹配的往来单位', + emptyText: _summaryPartnerId == null ? '暂无未结清的应收 / 应付' : '没有匹配的往来单位', mobileCards: rows .map( (r) => MobileListCard( @@ -682,26 +680,35 @@ class _FinanceScreenState extends ConsumerState { '往来单位', // 表头「往来单位」文字右边内嵌下拉(验收反馈:由卡标题行搜索框 // 改到此处,与 _flowTable 往来单位筛选同款 ComboSearchField)。 - header: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - '往来单位', - style: TextStyle( - fontSize: AppDims.fsSm, - fontWeight: FontWeight.w600, - color: t.muted, + // 外包 SizedBox 固定高=ComboSearchField 自身高度:Row 的 + // crossAxisAlignment.center 依赖两个子项各自的内在高度居中, + // 标签文字行高在不同字体下可能与 34 有偏差,导致下拉在表头行 + // 里视觉偏上(验收反馈);显式钉住 Row 高度消除该偏差,不改 + // 表头行 pad 11/14 的既有行高口径。 + header: SizedBox( + height: 34, + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + '往来单位', + style: TextStyle( + fontSize: AppDims.fsSm, + fontWeight: FontWeight.w600, + color: t.muted, + ), ), - ), - const SizedBox(width: 10), - ComboSearchField( - options: partnerOptions, - selectedId: _summaryPartnerId, - hint: '搜索往来单位', - width: 180, - onChanged: _setSummaryPartner, - ), - ], + const SizedBox(width: 10), + ComboSearchField( + options: partnerOptions, + selectedId: _summaryPartnerId, + hint: '往来单位', + width: 180, + onChanged: _setSummaryPartner, + ), + ], + ), ), ), const DsColumn('recv', '应收', numeric: true), @@ -740,9 +747,8 @@ class _FinanceScreenState extends ConsumerState { fontFamily: AppFonts.mono, fontFamilyFallback: AppFonts.monoFallback, fontWeight: FontWeight.w600, - color: r.net > 0 - ? t.success - : (r.net < 0 ? t.danger : t.text), + color: + r.net > 0 ? t.success : (r.net < 0 ? t.danger : t.text), ), ), InkWell( @@ -806,14 +812,12 @@ class _FinanceScreenState extends ConsumerState { // stock_out_list_screen.dart 客户 ComboSearchField 写法)。仅桌面 // 工具栏放置,移动端对应筛选在 _timeRow 尾部的「往来单位」chip → sheet。 ComboSearchField( - options: - (ref.watch(allPartnersProvider).valueOrNull?.data ?? - const []) - .map( - (p) => - OptionItem(id: p.id, name: p.name, code: p.code), - ) - .toList(), + options: (ref.watch(allPartnersProvider).valueOrNull?.data ?? + const []) + .map( + (p) => OptionItem(id: p.id, name: p.name, code: p.code), + ) + .toList(), selectedId: _partnerId, hint: '往来单位', width: 180, @@ -971,8 +975,7 @@ class _FinanceScreenState extends ConsumerState { MobileCardField('状态', r.status == 'open' ? '未结清' : '已结清'), if (r.remark?.isNotEmpty == true) MobileCardField('备注', r.remark), ], - actions: - (r.status == 'open' && + actions: (r.status == 'open' && (r.type == 'receivable' || r.type == 'payable')) ? [ WriteGuard( @@ -990,23 +993,22 @@ class _FinanceScreenState extends ConsumerState { /// delta 箭头/色调映射(与 DsKpi 同规则:▲/▼ 文本字符)。 String _mDeltaText(String text, DsKpiDelta tone) => switch (tone) { - DsKpiDelta.up => '▲ $text', - DsKpiDelta.down => '▼ $text', - DsKpiDelta.neutral => text, - }; + DsKpiDelta.up => '▲ $text', + DsKpiDelta.down => '▼ $text', + DsKpiDelta.neutral => text, + }; MKpiDeltaTone _mTone(DsKpiDelta tone) => switch (tone) { - DsKpiDelta.up => MKpiDeltaTone.up, - DsKpiDelta.down => MKpiDeltaTone.down, - DsKpiDelta.neutral => MKpiDeltaTone.normal, - }; + DsKpiDelta.up => MKpiDeltaTone.up, + DsKpiDelta.down => MKpiDeltaTone.down, + DsKpiDelta.neutral => MKpiDeltaTone.normal, + }; /// 窄屏 KPI 2×2(原型 .m-kpi:本月收入 / 本月支出 / 应收合计 / 应付合计)。 Widget _mKpis(dynamic t) { final outSum = ref.watch(stockOutSummaryProvider).valueOrNull; final inSum = ref.watch(stockInSummaryProvider).valueOrNull; - final rows = - ref.watch(financePartnerRowsProvider).valueOrNull ?? + final rows = ref.watch(financePartnerRowsProvider).valueOrNull ?? const []; var recv = 0.0, pay = 0.0, openCount = 0; for (final r in rows) { @@ -1054,32 +1056,32 @@ class _FinanceScreenState extends ConsumerState { /// 三分段列表体:m-section 计数标题 + 卡片流(应收/应付=往来汇总,流水=收支记录)。 List _mSegBody(dynamic t, List flows) { Widget section(String title, int count) => Padding( - padding: const EdgeInsets.fromLTRB(2, 16, 2, 8), - child: Text( - '$title · 共 $count', - style: TextStyle( - fontSize: AppDims.fsSm, - fontWeight: FontWeight.w700, - letterSpacing: .4, - color: t.muted, - ), - ), - ); + padding: const EdgeInsets.fromLTRB(2, 16, 2, 8), + child: Text( + '$title · 共 $count', + style: TextStyle( + fontSize: AppDims.fsSm, + fontWeight: FontWeight.w700, + letterSpacing: .4, + color: t.muted, + ), + ), + ); Widget empty([String msg = '暂无数据']) => Padding( - padding: const EdgeInsets.all(24), - child: Center( - child: Text( - msg, - style: TextStyle(color: t.muted, fontSize: AppDims.fsSm), - ), - ), - ); + padding: const EdgeInsets.all(24), + child: Center( + child: Text( + msg, + style: TextStyle(color: t.muted, fontSize: AppDims.fsSm), + ), + ), + ); List stacked(List cards) => [ - for (var i = 0; i < cards.length; i++) ...[ - if (i > 0) const SizedBox(height: 10), - cards[i], - ], - ]; + for (var i = 0; i < cards.length; i++) ...[ + if (i > 0) const SizedBox(height: 10), + cards[i], + ], + ]; if (_mSeg == 2) { return [ @@ -1216,34 +1218,35 @@ class _PartnerSheetBodyState extends State<_PartnerSheetBody> { required String name, required bool selected, required VoidCallback onTap, - }) => InkWell( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 13, horizontal: 4), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: t.borderSubtle)), - ), - child: Row( - children: [ - Expanded( - child: Text( - name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: AppDims.fsBody, - fontWeight: selected ? FontWeight.w600 : FontWeight.w400, - color: selected ? t.primary : t.text, - ), - ), + }) => + InkWell( + onTap: onTap, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 13, horizontal: 4), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: t.borderSubtle)), ), - if (selected) ...[ - const SizedBox(width: 8), - Icon(LucideIcons.check, size: 18, color: t.primary), - ], - ], - ), - ), - ); + child: Row( + children: [ + Expanded( + child: Text( + name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: AppDims.fsBody, + fontWeight: selected ? FontWeight.w600 : FontWeight.w400, + color: selected ? t.primary : t.text, + ), + ), + ), + if (selected) ...[ + const SizedBox(width: 8), + Icon(LucideIcons.check, size: 18, color: t.primary), + ], + ], + ), + ), + ); return Column( mainAxisSize: MainAxisSize.min, diff --git a/client/test/finance_summary_search_test.dart b/client/test/finance_summary_search_test.dart index a80d681..acdddb9 100644 --- a/client/test/finance_summary_search_test.dart +++ b/client/test/finance_summary_search_test.dart @@ -77,6 +77,9 @@ class _FakeFinanceRepository extends FinanceRepository { Future> trend({int months = 6}) async => const []; } +/// 第 4 条「未挂账供应商」故意不出现在 partnerSummary() 里,用于验证下拉 +/// 候选=全量往来单位(而非只列汇总行里出现的单位):选中它后汇总应展示 +/// 既有「没有匹配的往来单位」空态。 class _FakeAllPartners extends PartnerListNotifier { @override Future> build() async => const PageResult( @@ -84,8 +87,9 @@ class _FakeAllPartners extends PartnerListNotifier { Partner(id: 1, name: '华东酒类批发', type: 'customer'), Partner(id: 2, name: '金樽商贸', type: 'customer'), Partner(id: 3, name: '茅台华南经销', type: 'supplier'), + Partner(id: 4, name: '未挂账供应商', type: 'supplier'), ], - total: 3, + total: 4, page: 1, pageSize: 1000, ); @@ -94,10 +98,10 @@ class _FakeAllPartners extends PartnerListNotifier { List _overrides() => [ financeRepositoryProvider.overrideWith((ref) => _FakeFinanceRepository()), allPartnersProvider.overrideWith(() => _FakeAllPartners()), - stockOutSummaryProvider.overrideWith( - (ref) async => const StockSummary(monthAmount: 0, lastMonthAmount: 0)), - stockInSummaryProvider.overrideWith( - (ref) async => const StockSummary(monthAmount: 0, lastMonthAmount: 0)), + stockOutSummaryProvider.overrideWith((ref) async => + const StockSummary(monthAmount: 0, lastMonthAmount: 0)), + stockInSummaryProvider.overrideWith((ref) async => + const StockSummary(monthAmount: 0, lastMonthAmount: 0)), isReadonlyProvider.overrideWithValue(false), ]; @@ -134,13 +138,13 @@ void main() { expect(find.text('金樽商贸'), findsOneWidget); expect(find.text('茅台华南经销'), findsOneWidget); - // 定位表头内嵌的 ComboSearchField(按构造参数 hint 匹配,避免与 - // _flowTable toolbar 的往来单位 ComboSearchField(hint:'往来单位') - // 混淆;选中后触发器文案会变成往来单位名,故不能用显示文字定位)。 - final combo = find.byWidgetPredicate( - (w) => w is ComboSearchField && w.hint == '搜索往来单位', - ); - expect(combo, findsOneWidget); + // 定位表头内嵌的 ComboSearchField:验收反馈后候选/占位文案与 + // _flowTable toolbar 的往来单位 ComboSearchField 完全同款(同为 + // hint:'往来单位'),不能再靠 hint/显示文字区分;改用构建顺序—— + // 汇总表(_summaryTable)先于流水表(_flowTable)出现在页面里, + // 故 ComboSearchField 的第一个即汇总表头这个。 + final combo = find.byType(ComboSearchField).first; + expect(find.byType(ComboSearchField), findsNWidgets(2)); await tester.ensureVisible(combo); await tester.pumpAndSettle(); @@ -168,6 +172,30 @@ void main() { expect(find.text('金樽商贸'), findsOneWidget); expect(find.text('茅台华南经销'), findsOneWidget); }); + + testWidgets('候选=全量往来单位;选中汇总里没有行的单位显示空态', (tester) async { + await _pumpFinance(tester, size: const Size(1280, 900)); + + final combo = find.byType(ComboSearchField).first; + await tester.ensureVisible(combo); + await tester.pumpAndSettle(); + await tester.tap(combo); + await tester.pumpAndSettle(); + + // 候选来自全量往来单位(4 条,含汇总里没有余额行的「未挂账供应商」), + // 而不再是「共 3 条结果」(旧口径=当前汇总行往来单位)。 + expect(find.text('共 4 条结果'), findsOneWidget); + expect(find.widgetWithText(InkWell, '未挂账供应商'), findsOneWidget); + + await tester.tap(find.widgetWithText(InkWell, '未挂账供应商')); + await tester.pumpAndSettle(); + + // 该单位在汇总里没有余额行 → 走既有「没有匹配的往来单位」空态。 + expect(find.text('没有匹配的往来单位'), findsOneWidget); + expect(find.text('华东酒类批发'), findsNothing); + expect(find.text('金樽商贸'), findsNothing); + expect(find.text('茅台华南经销'), findsNothing); + }); }); group('移动应收/应付分段往来单位搜索', () { diff --git a/client/test/golden/goldens/finance_a.png b/client/test/golden/goldens/finance_a.png index 9812ceb..09f9483 100644 Binary files a/client/test/golden/goldens/finance_a.png and b/client/test/golden/goldens/finance_a.png differ diff --git a/client/test/golden/goldens/finance_b.png b/client/test/golden/goldens/finance_b.png index cb403ae..bda3a41 100644 Binary files a/client/test/golden/goldens/finance_b.png and b/client/test/golden/goldens/finance_b.png differ diff --git a/client/test/golden/goldens/finance_c.png b/client/test/golden/goldens/finance_c.png index 4506cca..935f4c3 100644 Binary files a/client/test/golden/goldens/finance_c.png and b/client/test/golden/goldens/finance_c.png differ diff --git a/design/CONTRACT.md b/design/CONTRACT.md index 1939831..2d2a658 100644 --- a/design/CONTRACT.md +++ b/design/CONTRACT.md @@ -105,7 +105,7 @@ AppTokens 目前**仅颜色**。原型还驱动: | 基础数据(移动) | `m-products.html` | 同上窄屏(卡片流) | 同步 | ✅ golden 自比 | ✅ golden 自比 | ✅ golden 自比 | | 入库列表(桌/移) | `stock-in-list.html` | `stock_in_list_screen.dart` | 同步 | ✅ 副标 + 共享 StatusPill(草稿/待审/已审/已拒);**2026-07-14 六项优化**:详情抽屉明细增加生产日期+批次号两列(抽屉加宽 660)、状态筛选改多选 chip 且默认勾选「草稿+待审核」、新建单默认填充默认仓库(原型 stock-in-list.html/stock-in.js 同步);fidelity a 3.323% / b 2.319% / c 3.633%(均 ≤ 阈值 6%),移动 golden 自比全绿 | ✅ golden | ✅ golden | | 出库列表(桌/移) | `stock-out-list.html` | `stock_out_list_screen.dart` | 同步 | ✅ 副标 + 共享 StatusPill;**2026-07-14 六项优化**:详情抽屉明细同增生产日期+批次号两列(抽屉 660)、状态筛选改多选 chip 且默认「草稿+待审核」、新建单默认填充默认仓库(原型 stock-out-list.html 同步);fidelity a 3.228% / b 2.217% / c 3.538%(均 ≤ 阈值 6%),移动 golden 自比全绿 | ✅ golden | ✅ golden | -| 财务(桌/移) | `finance.html` | `finance_screen.dart` | 同步 | ✅ **Phase2 重建**:时间范围 chips(真实过滤)+KPI 4 卡(stock summary 环比)+收支趋势柱状图(DsBarChart, /finance/trend)+应收应付汇总(/finance/summary)+流水表+往来抽屉+登记收支(补往来单位);**2026-07-14 六项优化**:流水表筛选新增「往来单位」下拉、时间范围统一改用通用自定义时间组件(原型 finance.html/m-finance.html 同步);fidelity a 4.036% / b 3.131% / c 4.340%(均 ≤ 阈值 6%),移动 golden 自比全绿;**2026-07-14 追加**:应收/应付汇总卡头部新增「往来单位」搜索——本地即时过滤(`/finance/summary` 全量非分页,搜索口径=显示口径),桌面 `DsSearchBox`(`_secHead` trailing)/移动 应收·应付 分段头 `MSearchRow`(流水分段沿用既有 chip→sheet 单选,不重复),原型 finance.html `.sum-search` / m-finance.html 应收应付分段 `.m-search` 同步,finance 相关 6 个整屏 golden + m_finance 3 个 golden 已按新布局 `--update-goldens`;**2026-07-14 验收反馈调整**:桌面「往来单位」搜索由卡标题行 `DsSearchBox` 挪进汇总表表头「往来单位」列头右侧,改为下拉单选 `ComboSearchField`(同 `_flowTable` 往来单位筛选控件,选中精确匹配一行/× 清除恢复全量,候选=当前汇总行往来单位);原型 `.sec-head .sum-search` 移除,改 `.th-party-wrap` 内嵌 `.combo` + `openSearchMenu` 弹层;移动端未动。desktop `finance` golden 3 主题已 `--update-goldens`(3.11% 差异,目检确认新版式),`finance_mobile`/`m_finance` 无变化、原样通过 | ✅ fidelity | ✅ fidelity | +| 财务(桌/移) | `finance.html` | `finance_screen.dart` | 同步 | ✅ **Phase2 重建**:时间范围 chips(真实过滤)+KPI 4 卡(stock summary 环比)+收支趋势柱状图(DsBarChart, /finance/trend)+应收应付汇总(/finance/summary)+流水表+往来抽屉+登记收支(补往来单位);**2026-07-14 六项优化**:流水表筛选新增「往来单位」下拉、时间范围统一改用通用自定义时间组件(原型 finance.html/m-finance.html 同步);fidelity a 4.036% / b 3.131% / c 4.340%(均 ≤ 阈值 6%),移动 golden 自比全绿;**2026-07-14 追加**:应收/应付汇总卡头部新增「往来单位」搜索——本地即时过滤(`/finance/summary` 全量非分页,搜索口径=显示口径),桌面 `DsSearchBox`(`_secHead` trailing)/移动 应收·应付 分段头 `MSearchRow`(流水分段沿用既有 chip→sheet 单选,不重复),原型 finance.html `.sum-search` / m-finance.html 应收应付分段 `.m-search` 同步,finance 相关 6 个整屏 golden + m_finance 3 个 golden 已按新布局 `--update-goldens`;**2026-07-14 验收反馈调整**:桌面「往来单位」搜索由卡标题行 `DsSearchBox` 挪进汇总表表头「往来单位」列头右侧,改为下拉单选 `ComboSearchField`(同 `_flowTable` 往来单位筛选控件,选中精确匹配一行/× 清除恢复全量,候选=当前汇总行往来单位);原型 `.sec-head .sum-search` 移除,改 `.th-party-wrap` 内嵌 `.combo` + `openSearchMenu` 弹层;移动端未动。desktop `finance` golden 3 主题已 `--update-goldens`(3.11% 差异,目检确认新版式),`finance_mobile`/`m_finance` 无变化、原样通过;**2026-07-14 验收反馈2**(实机截图 3 处细节):①下拉候选由「仅当前汇总行往来单位」改为「全量往来单位」(`allPartnersProvider`,与 `_flowTable` toolbar 同源),选中一个汇总没有余额行的单位时走既有「没有匹配的往来单位」空态;②占位符叠词修复——`ComboSearchField.hint` 由 `'搜索往来单位'` 改 `'往来单位'`(内部会自动拼「搜索」前缀),弹层内搜索框恢复正常显示「搜索往来单位…」,收起态触发器文案对齐 `_flowTable` 写法同为「往来单位」;③表头行下拉垂直位置——`header` 外包 `SizedBox(height: 34)` 显式钉住 Row 高度消除潜在字体行高偏差,不改表头行 pad 11/14 既有行高口径。原型 finance.html 同步:`ALL_PARTNERS`(`SUMMARY` 全部单位 + 1 个无余额行的「鼎丰超市」演示空态)替换 `sumPartyId`/`SUMMARY` 候选、`#sumPartyInput` 收起态 placeholder 改「往来单位」;`.th-party-wrap{align-items:center}` + 浏览器 `th` 默认 `vertical-align:middle` 本就居中,未改 CSS。desktop `finance` golden 3 主题已 `--update-goldens`(0.04% 差异,目检确认新候选/占位文案,表头对齐无回归),`finance_mobile`/`m_finance` 无变化、原样通过 | ✅ fidelity | ✅ fidelity | | 设备管理(桌/移) | `devices.html` | `device_management_screen.dart` | 同步 | ✅ **Phase2 重建**:会话表(DsTable)+外设卡网格(custom_fields.peripherals 本地存档)+打印模板;fidelity 2.4–3.0%≤8% | ✅ fidelity | ✅ fidelity | | 系统设置(桌/移) | `settings.html` | `settings_screen.dart` | 同步 | ✅ **Phase2 重建**;假「系统参数」已删;fidelity 1.7–2.3%≤8%;**2026-07-10 授权管理面板迁出**(提升为独立一级屏 `license.html`),subnav 剩 门店信息/用户管理/偏好——**真实端已同步完成**(`settings_screen.dart` 子导航同步摘除授权管理项,golden 已按新态重生成,见授权管理两行) | ✅ fidelity | ✅ fidelity | | 用户管理(桌/移) | `users.html` | `users_screen.dart`(`/settings/users`) | 同步 | ✅ **Phase2 新独立页**:KPI 4 卡+搜索/角色筛选+rcard 弹窗,角色四级拉平;fidelity 1.3–2.1%≤8% | ✅ fidelity | ✅ fidelity | diff --git a/design/prototype/screens/finance.html b/design/prototype/screens/finance.html index fda3c0a..b5b4cbf 100644 --- a/design/prototype/screens/finance.html +++ b/design/prototype/screens/finance.html @@ -115,7 +115,7 @@

应收 / 应付 汇总

按往来单位 · 点击行查看流水
- + @@ -189,23 +189,27 @@ const SUMMARY=[ ]; function yuan(n){ return '¥'+n.toLocaleString(); } // 汇总表头「往来单位」下拉筛选(对齐 ComboSearchField:单选精确匹配一行,非 -// 关键字子串过滤;候选=当前汇总行往来单位,搜索口径=显示口径,不用全量往来 -// 单位库,避免选到无余额单位出空表) -let sumPartyId=null; // 选中的 SUMMARY 下标;null=全部 +// 关键字子串过滤;验收反馈改版:候选=全量往来单位(与收支流水 toolbar 往来 +// 单位筛选同源),而非只列当前汇总行里出现的单位——选中一个汇总没有余额 +// 行的单位时,走既有「没有匹配的往来单位」空态)。 +// ALL_PARTNERS 模拟真实 allPartnersProvider 全量库:含 SUMMARY 全部单位 + +// 1 个汇总里没有余额行的「鼎丰超市」,用于还原空态场景。 +const ALL_PARTNERS=[...SUMMARY.map(s=>s.name),'鼎丰超市']; +let sumPartyName=null; // 选中的往来单位名;null=全部 function openSumPartyFilter(t){ - openSearchMenu(t, SUMMARY.map((s,i)=>({v:i,label:s.name,sel:i===sumPartyId})), v=>{ - sumPartyId=Number(v); closeMenus(); buildSummary(); + openSearchMenu(t, ALL_PARTNERS.map(name=>({v:name,label:name,sel:name===sumPartyName})), v=>{ + sumPartyName=v; closeMenus(); buildSummary(); }, {placeholder:'搜索往来单位…'}); } // combo 已选中值(.has)时,点击右侧图标(此时为 ×)清除,不弹出下拉 function sumPartyCafClick(e){ - if(sumPartyId!=null){ e.stopPropagation(); sumPartyId=null; buildSummary(); } + if(sumPartyName!=null){ e.stopPropagation(); sumPartyName=null; buildSummary(); } } function buildSummary(){ - const rows=sumPartyId==null?SUMMARY.map((s,i)=>({...s,i})):SUMMARY.map((s,i)=>({...s,i})).filter(s=>s.i===sumPartyId); - const has=sumPartyId!=null; + const rows=sumPartyName==null?SUMMARY.map((s,i)=>({...s,i})):SUMMARY.map((s,i)=>({...s,i})).filter(s=>s.name===sumPartyName); + const has=sumPartyName!=null; document.getElementById('sumPartyCombo').classList.toggle('has',has); - document.getElementById('sumPartyInput').value=has?SUMMARY[sumPartyId].name:''; + document.getElementById('sumPartyInput').value=has?sumPartyName:''; document.getElementById('sumPartyCaf').innerHTML=has ?'' :'';
往来单位
往来单位
应收应付净额操作