signal event selector

This commit is contained in:
Timi
2026-09-12 17:01:27 +08:00
parent 194a55a03f
commit 584fbfadf5
2 changed files with 61 additions and 59 deletions
+56 -53
View File
@@ -1,26 +1,25 @@
<template>
<div v-can="permissionCodes.eventRecord.create" class="quick-sign-in-page">
<space class="content-margin" direction="vertical" v-entrance-transition>
<div class="event-panel">
<event-selector
v-if="!isEventLoading && !eventLoadFailed"
:model-value="selectedEventIdList"
:event-list="eventList"
required-mark
@update:model-value="handleEventSelectionChange"
/>
<div v-else-if="isEventLoading" class="empty-block">正在加载登记事件</div>
<div v-else class="event-load-error">
<span>登记事件加载失败</span>
<t-button size="small" theme="primary" variant="text" @click="loadActions">重试</t-button>
</div>
<div class="tips red">事件可多选,请注意勾选的登记事件</div>
</div>
<t-cell-group v-if="!isEventLoading && !eventLoadFailed" theme="card">
<t-cell
title="登记事件"
:note="selectedEventName"
arrow
@click="eventPopupVisible = true"
>
<template #left-icon>
<t-icon name="task-setting" />
</template>
</t-cell>
</t-cell-group>
<div v-else-if="isEventLoading" class="center-tips">正在加载登记事件</div>
<div v-else class="center-tips">登记事件加载失败</div>
<event-option-selector
v-model="selectedOptionSelectionMap"
:event-list="eventList"
:selected-event-id-list="selectedEventIdList"
/>
<div class="content-margin">
<code-scanner
visible
:session-key="scannerSessionKey"
@@ -29,7 +28,7 @@
@decode="handleDecodedText"
@status-change="handleScanStatusChange"
/>
</space>
</div>
<t-cell-group class="auto-register-setting" theme="card" v-entrance-transition="55">
<t-cell title="识别成功自动登记">
<template #right-icon>
@@ -46,7 +45,7 @@
:disabled="!canSubmitRegister"
:loading="submitting"
v-entrance-transition="70"
@click="doSubmit"
@click="doSubmit()"
>登记</t-button>
<customer-profile-card
v-if="matchedCustomer"
@@ -120,6 +119,29 @@
@change="handleRecordPhotoSelected"
>
</div>
<bottom-popup
v-model="eventPopupVisible"
title="选择登记事件"
left-button-text="关闭"
right-button-text=""
@left-button-click="eventPopupVisible = false"
>
<div class="event-popup">
<event-selector
v-if="!isEventLoading && !eventLoadFailed"
:model-value="selectedEventIdList"
:event-list="eventList"
selection-mode="single"
label=""
@update:model-value="handleEventSelectionChange"
/>
<div v-else-if="isEventLoading" class="empty-block">正在加载登记事件</div>
<div v-else class="event-load-error">
<span>登记事件加载失败</span>
<t-button size="small" theme="primary" variant="text" @click="loadActions">重试</t-button>
</div>
</div>
</bottom-popup>
</template>
<script setup lang="ts">
@@ -145,7 +167,7 @@ import { compressUploadImageList } from "@/utils/imageCompression";
import { Storage, Time } from "timi-web";
import { AttachmentAPI, type Attachment } from "timi-web-api";
import EventSelector from "@/components/EventSelector.vue";
import { Space } from "timi-tdesign-mobile";
import { BottomPopup, Space } from "timi-tdesign-mobile";
defineOptions({
name: "QuickSignInPage"
@@ -164,9 +186,11 @@ const eventList = ref<EventItem[]>([]);
const selectedOptionSelectionMap = reactive<EventOptionSelectionMap>({});
const isEventLoading = ref(false);
const eventLoadFailed = ref(false);
const eventPopupVisible = ref(false);
const selectedEventList = computed(() => selectedEventIdList.value
.map(eventId => eventList.value.find(item => normalizeEventId(item) === eventId))
.filter((item): item is EventItem => !!item));
const selectedEventName = computed(() => selectedEventList.value[0]?.name || "请选择登记事件");
const selectedNumberEventList = computed(() => selectedEventList.value.filter(item => item.valueType === "NUMBER"));
const selectedRequiredPhotoEventList = computed(() => selectedEventList.value.filter(item => item.requirePhoto === true));
@@ -212,12 +236,13 @@ function buildInitialSelectedEventIdList(): string[] {
function normalizeSelectedEventIdList(eventIdList: string[]): string[] {
const validEventIdSet = new Set(eventList.value.map(normalizeEventId).filter(Boolean));
return [...new Set(eventIdList.map(String))].filter(eventId => validEventIdSet.has(eventId));
return [...new Set(eventIdList.map(String))].filter(eventId => validEventIdSet.has(eventId)).slice(0, 1);
}
async function handleEventSelectionChange(eventIdList: string[]): Promise<void> {
selectedEventIdList.value = normalizeSelectedEventIdList(eventIdList);
syncStoredEventId();
eventPopupVisible.value = false;
}
function resolveRecordOptionGroupList(eventId: string) {
@@ -279,7 +304,7 @@ async function handleDecodedText(rawText: string): Promise<void> {
}
scanStatus.value = `已识别 ${normalizedText},可直接登记`;
if (autoRegisterEnabled.value) {
await doSubmit();
await doSubmit(true);
}
return;
}
@@ -424,7 +449,7 @@ function buildPhotoAttachmentList(): Array<Partial<Attachment>> {
}));
}
async function doSubmit(): Promise<void> {
async function doSubmit(isAutoRegister = false): Promise<void> {
const customer = matchedCustomer.value;
if (!customer) {
return;
@@ -465,7 +490,11 @@ async function doSubmit(): Promise<void> {
attachmentList: buildPhotoAttachmentList()
})));
registeredCustomerIdSet.add(customerId);
scanStatus.value = `登记成功:${customer.name || customer.code || scanCode.value}。`;
const customerText = customer.name || customer.code || scanCode.value || "客户";
scanStatus.value = `登记成功:${customerText}。`;
if (isAutoRegister) {
Message.success(`自动登记成功:${customerText}`);
}
scanCode.value = "";
matchedCustomer.value = undefined;
recordPhotoItemList.value = [];
@@ -493,18 +522,6 @@ async function doSubmit(): Promise<void> {
display: flex;
flex-direction: column;
.event-panel {
padding: .75rem 1rem;
background: rgba(255, 255, 255, .94);
box-shadow: 0 .75rem 2rem rgba(15, 23, 42, .08);
border-radius: .875rem;
.tips {
margin-top: .5rem;
text-align: center;
}
}
.input-form {
padding: .5rem 0;
background: rgba(255, 255, 255, .94);
@@ -526,24 +543,6 @@ async function doSubmit(): Promise<void> {
display: none;
}
.empty-block,
.event-load-error {
color: #52607a;
min-height: 4rem;
align-items: center;
justify-content: center;
}
.empty-block {
display: flex;
}
.event-load-error {
gap: .5rem;
display: grid;
text-align: center;
}
.code-box {
padding: .875rem;
background: #f7faff;
@@ -581,6 +580,10 @@ async function doSubmit(): Promise<void> {
}
}
.event-popup {
padding: 1rem;
}
:global(html.theme-dark) {
.quick-sign-in-page {
.panel,
-1
View File
@@ -208,7 +208,6 @@ onUnmounted(() => {
.tips {
font-size: .875rem;
margin-top: 1rem;
text-indent: 2em;
}
}