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