feat: 管理端公账支付与确认、锁店遮罩及表单提交修复

新增公账账单/到账确认页与全局锁店组件;系统配置补公账参数面板;
统一弹窗 onConfirm 校验提交,并完善订单详情与门店相关交互。
This commit is contained in:
李琦
2026-08-21 12:51:42 +08:00
parent 66e666754a
commit 879efb8f29
145 changed files with 7326 additions and 884 deletions

View File

@@ -88,4 +88,14 @@ export function setupVbenForm<
COMPONENT_BIND_EVENT_MAP[key] = modelPropNameMap[key];
}
}
// 内置 Vben* 等不在 globalShareState 里时,仍要能按 modelPropNameMap 绑定
// (否则 baseModelPropName=value + changeEventFallback 会把原生 Event 写进登录表单)
if (modelPropNameMap) {
for (const [component, propName] of Object.entries(modelPropNameMap)) {
if (propName) {
COMPONENT_BIND_EVENT_MAP[component as BaseFormComponentType] = propName;
}
}
}
}

View File

@@ -314,6 +314,36 @@ function resolveModelPropName() {
);
}
/**
* 从 change/input 回调参数里取出真正的字段值。
* antd Input 等会把原生 Event 丢进 onChange;必须取 target.value,
* 否则表单会写成 "[object Event]"(登录页账号/密码已踩过)。
*/
function resolveChangePayload(
event: Record<string, any>,
eventField?: null | string,
) {
if (!isEventObjectLike(event)) {
return event;
}
const target = event?.target;
if (!target || !isObject(target)) {
return event;
}
// v-model:value → target.value;v-model:modelValue 时原生节点没有 modelValue,回退 value
if (
eventField &&
eventField !== 'modelValue' &&
Reflect.has(target, eventField)
) {
return target[eventField];
}
if (Reflect.has(target, 'value')) {
return target.value;
}
return event;
}
function fieldBindEvent(
componentField: Record<string, any>,
bindEventField: null | string | undefined,
@@ -325,7 +355,7 @@ function fieldBindEvent(
// antd design 的一些组件会传递一个 event 对象
if (modelValue && isObject(modelValue) && bindEventField) {
value = isEventObjectLike(modelValue)
? modelValue?.target?.[bindEventField]
? resolveChangePayload(modelValue, bindEventField)
: (modelValue?.[bindEventField] ?? modelValue);
}
@@ -333,21 +363,26 @@ function fieldBindEvent(
const eventField = bindEventField;
function handleChangeEvent(event: Record<string, any>) {
const value = isEventObjectLike(event)
? (event?.target?.[eventField] ?? event)
: event;
return handler?.(value);
return handler?.(resolveChangePayload(event, eventField));
}
// modelValue 组件已有 onUpdate:modelValue,再挂原生 onChange 会把 Event 写进表单
const shouldBindChangeFallback =
changeEventFallback && eventField !== 'modelValue';
return {
[`onUpdate:${eventField}`]: handler,
[eventField]: value === undefined ? emptyStateValue : value,
onChange: changeEventFallback ? handleChangeEvent : undefined,
onChange: shouldBindChangeFallback ? handleChangeEvent : undefined,
onInput: undefined,
};
}
// 未配置 bind 字段名时走默认 modelValue;不要把原生 Event 原样交给 handleChange
return {
onChange: changeEventFallback ? componentField.onChange : undefined,
onChange: changeEventFallback
? (event: Record<string, any>) =>
componentField.onChange?.(resolveChangePayload(event, 'value'))
: undefined,
onInput: undefined,
};
}

View File

@@ -82,6 +82,13 @@ function handleKeyDownEnter(event: KeyboardEvent) {
if (target?.closest('.ant-select-open')) {
return;
}
// 门店多选气泡(Teleport 到 body):面板打开时回车是选用,跳过提交
if (
target?.closest('.store-multi-search') &&
document.querySelector('.store-multi-search__panel')
) {
return;
}
// 日期/时间选择器:与 Select 一致的两段式语义——
// 面板打开时回车是「确认日期选择」(keydown 同步阶段面板 DOM 尚未被异步移除,仍可命中),跳过提交;
// 面板关闭后的下一次回车才提交,即「选完日期第二次回车即搜索」