feat(client): 出入库列表按原型重建(KPI/详情抽屉/详细搜索/工具栏/选中复制/窗口尺寸)
- 列表重建:KPI 卡、状态+时间列、操作改眼睛开右侧详情抽屉、重置右置 - 详情抽屉(order_detail_drawer) 100% 还原原型 + SelectionArea 可选中复制 - 详细搜索弹窗:ComboSearchField/滚轮日期、字段重构、白底盒子按钮 - 工具栏:搜索框×清除+占位精简、供应商/客户下拉取全部、状态菜单收窄 - 加载不白屏(半透明遮罩)、输入框与下拉等高、windows/macOS 默认窗口尺寸调大 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -119,7 +119,13 @@ class DsChip extends StatelessWidget {
|
||||
final String label;
|
||||
final String? value; // 选中值(.cv);非空即 on 态
|
||||
final VoidCallback? onTap;
|
||||
const DsChip({super.key, required this.label, this.value, this.onTap});
|
||||
final VoidCallback? onClear; // 选中态下点 × 单独清除该筛选(不触发展开菜单)
|
||||
const DsChip(
|
||||
{super.key,
|
||||
required this.label,
|
||||
this.value,
|
||||
this.onTap,
|
||||
this.onClear});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -150,7 +156,15 @@ class DsChip extends StatelessWidget {
|
||||
fontWeight: FontWeight.w600)),
|
||||
],
|
||||
const SizedBox(width: 7),
|
||||
Icon(Icons.keyboard_arrow_down, size: 14, color: t.faint),
|
||||
// 选中且提供 onClear → 展示可点 ×(清该筛选);否则展示下拉箭头。
|
||||
if (on && onClear != null)
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: onClear,
|
||||
child: Icon(Icons.close, size: 14, color: t.muted),
|
||||
)
|
||||
else
|
||||
Icon(Icons.keyboard_arrow_down, size: 14, color: t.faint),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -207,9 +221,54 @@ class DsSearchBox extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
// 有输入时显示 × 清除(清空并触发一次空关键词搜索)。
|
||||
if (controller != null)
|
||||
ValueListenableBuilder<TextEditingValue>(
|
||||
valueListenable: controller!,
|
||||
builder: (context, value, _) {
|
||||
if (value.text.isEmpty) return const SizedBox.shrink();
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
controller!.clear();
|
||||
onChanged?.call('');
|
||||
onSubmitted?.call('');
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 6),
|
||||
child: Icon(Icons.close, size: 14, color: t.muted),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 加载遮罩(reload 时叠在旧内容之上):轻微半透明底 + 屏幕中心进度圈。
|
||||
/// 搜索/筛选刷新时用它替代整屏白屏(见列表屏 skipLoadingOnReload)。
|
||||
class DsLoadingScrim extends StatelessWidget {
|
||||
const DsLoadingScrim({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = context.tokens;
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque, // 加载期间拦截点击,避免误触
|
||||
onTap: () {},
|
||||
child: ColoredBox(
|
||||
color: t.bg.withValues(alpha: 0.55),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: CircularProgressIndicator(strokeWidth: 3, color: t.primary),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ class _DsTableState extends State<DsTable> {
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
// 整宽拉伸:toolbar/表格/分页都填满卡片宽度(否则 toolbar 按内容宽居中→左侧留白)。
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (widget.toolbar != null) ...[
|
||||
Padding(
|
||||
|
||||
Reference in New Issue
Block a user