add event option
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
:customer="selectedCustomer"
|
||||
v-entrance-transition
|
||||
/>
|
||||
<div v-if="isEditMode" class="edit-point-tip red">涉及积分变动的数据不能修改,已产生积分流水的登记记录不会因修改客户、事件或时间而重算;如需修改这些事实,请删除后重新创建,删除会自动回流积分。</div>
|
||||
<event-selector
|
||||
v-model="selectedEventIdList"
|
||||
class="event-selector"
|
||||
@@ -51,6 +52,13 @@
|
||||
:disabled="isEditMode"
|
||||
required-mark
|
||||
/>
|
||||
<event-option-selector
|
||||
class="option-selector"
|
||||
v-model="selectedOptionSelectionMap"
|
||||
:event-list="eventList"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
:disabled="isSaving"
|
||||
/>
|
||||
<div v-if="!isEditMode && selectedNumberEventList.length" class="event-value-list">
|
||||
<t-form-item
|
||||
v-for="item in selectedNumberEventList"
|
||||
@@ -68,7 +76,6 @@
|
||||
/>
|
||||
</t-form-item>
|
||||
</div>
|
||||
<div v-if="isEditMode" class="edit-point-tip">已产生积分的登记记录不会因修改客户、事件或时间而重算;如需修改这些事实,请删除后重新创建。</div>
|
||||
<t-form-item v-if="showSourceValueInput" label="积分动作">
|
||||
<span class="picker-text" v-text="getPointActionText(sourceValueAction)" />
|
||||
</t-form-item>
|
||||
@@ -202,15 +209,17 @@ import CodeScanner from "@/components/CodeScanner.vue";
|
||||
import CustomerList from "@/components/CustomerList.vue";
|
||||
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
|
||||
import CustomerSelector from "@/components/CustomerSelector.vue";
|
||||
import EventOptionSelector from "@/components/EventOptionSelector.vue";
|
||||
import PhotoScroller from "@/components/PhotoScroller.vue";
|
||||
import EventSelector from "@/components/EventSelector.vue";
|
||||
import { useNavBarStore } from "@/store/navBarStore";
|
||||
import { useSettingStore } from "@/store/settingStore";
|
||||
import type { Customer } from "@/types/Customer";
|
||||
import type { EventItem } from "@/types/EventItem";
|
||||
import type { EventItem, EventOptionSelectionMap } from "@/types/EventItem";
|
||||
import type { EventRecord } from "@/types/EventRecord";
|
||||
import type { PointAction } from "@/types/Point";
|
||||
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||
import { buildEventOptionSelectionMap, resolveSelectedOptionGroupList, validateEventOptionSelection } from "@/utils/eventOption";
|
||||
import { getEventRecordPhotoURL, hasPhotoAttachment } from "@/utils/eventRecord";
|
||||
import { getEventNumberValuePlaceholder, resolveEventNumberValue } from "@/utils/eventValue";
|
||||
import { permissionCodes } from "@/utils/permission";
|
||||
@@ -240,7 +249,7 @@ type EditablePhoto = {
|
||||
const routeId = computed(() => String(route.params.id || ""));
|
||||
const isEditMode = computed(() => !!routeId.value);
|
||||
const pageAccess = computed(() => isEditMode.value ? permissionCodes.eventRecord.update : permissionCodes.eventRecord.create);
|
||||
const saveButtonText = computed(() => isEditMode.value ? "保存记录" : "提交");
|
||||
const saveButtonText = computed(() => isEditMode.value ? "保存" : "提交");
|
||||
|
||||
// ---------- 客户 ----------
|
||||
|
||||
@@ -406,6 +415,7 @@ function handleScanStatusChange(value: string): void {
|
||||
|
||||
const eventList = ref<EventItem[]>([]);
|
||||
const selectedEventIdList = ref<string[]>([]);
|
||||
const selectedOptionSelectionMap = reactive<EventOptionSelectionMap>({});
|
||||
const numberValueTextMap = reactive<Record<string, string>>({});
|
||||
const selectedNumberEventList = computed(() => selectedEventIdList.value
|
||||
.map(eventId => eventList.value.find(item => item.id === eventId))
|
||||
@@ -432,6 +442,11 @@ function appendRecordEvent(record: EventRecord): void {
|
||||
eventList.value = [record.event, ...eventList.value];
|
||||
}
|
||||
|
||||
function resolveRecordOptionGroupList(eventId: string) {
|
||||
const event = eventList.value.find(item => item.id === eventId);
|
||||
return event ? resolveSelectedOptionGroupList(event, selectedOptionSelectionMap) : [];
|
||||
}
|
||||
|
||||
function getNumberValuePlaceholder(event: EventItem): string {
|
||||
return getEventNumberValuePlaceholder(event);
|
||||
}
|
||||
@@ -629,6 +644,7 @@ async function submitRecord(): Promise<void> {
|
||||
await EventRecordAPI.createBatch(selectedEventIdList.value.map(eventId => ({
|
||||
eventId,
|
||||
customerIdList,
|
||||
selectedOptionGroupList: resolveRecordOptionGroupList(eventId),
|
||||
remark: note.value || "客户现场登记",
|
||||
registeredAt: buildRegisteredAt(),
|
||||
pointValue: showSourceValueInput.value ? resolveSourceValue() : undefined,
|
||||
@@ -646,6 +662,9 @@ async function submitRecord(): Promise<void> {
|
||||
for (const eventId of Object.keys(numberValueTextMap)) {
|
||||
delete numberValueTextMap[eventId];
|
||||
}
|
||||
for (const eventId of Object.keys(selectedOptionSelectionMap)) {
|
||||
delete selectedOptionSelectionMap[eventId];
|
||||
}
|
||||
await loadRecentRecordList();
|
||||
await settingStore.playRegisterSuccessSound();
|
||||
Message.success("登记已提交");
|
||||
@@ -664,6 +683,17 @@ function validateForm(): boolean {
|
||||
Message.warning("请至少选择一个登记事件");
|
||||
return false;
|
||||
}
|
||||
for (const eventId of selectedEventIdList.value) {
|
||||
const event = eventList.value.find(item => item.id === eventId);
|
||||
if (!event) {
|
||||
continue;
|
||||
}
|
||||
const optionError = validateEventOptionSelection(event, selectedOptionSelectionMap);
|
||||
if (optionError) {
|
||||
Message.warning(optionError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!validateRequiredPhotoList()) {
|
||||
return false;
|
||||
}
|
||||
@@ -698,9 +728,10 @@ async function updateRecord(): Promise<void> {
|
||||
}
|
||||
|
||||
await EventRecordAPI.update({
|
||||
...editingRecord.value,
|
||||
id: editingRecord.value.id,
|
||||
customerId: editingRecord.value.customerId,
|
||||
eventId: editingRecord.value.eventId,
|
||||
selectedOptionGroupList: resolveRecordOptionGroupList(editingRecord.value.eventId),
|
||||
remark: note.value,
|
||||
registeredAt: editingRecord.value.registeredAt,
|
||||
attachmentList: buildPhotoAttachmentList()
|
||||
@@ -749,6 +780,12 @@ async function loadRecordForEdit(): Promise<void> {
|
||||
customerCode.value = record.customer?.code || record.customerId || "";
|
||||
selectedCustomerIdList.value = record.customer?.id ? [record.customer.id] : [];
|
||||
selectedEventIdList.value = record.eventId ? [record.eventId] : [];
|
||||
for (const eventId of Object.keys(selectedOptionSelectionMap)) {
|
||||
delete selectedOptionSelectionMap[eventId];
|
||||
}
|
||||
if (record.eventId) {
|
||||
Object.assign(selectedOptionSelectionMap, buildEventOptionSelectionMap(record.eventId, record.selectedOptionGroupList));
|
||||
}
|
||||
registeredAtText.value = record.registeredAt ? Time.formatDateTime(new Date(record.registeredAt)) : "";
|
||||
note.value = record.remark || "";
|
||||
pointValueText.value = "";
|
||||
@@ -793,7 +830,7 @@ watch(customerCode, async (value) => {
|
||||
.registration-record-edit {
|
||||
gap: 1rem;
|
||||
display: flex;
|
||||
padding: calc(var(--app-nav-height) + 1rem) 0 4rem 0;
|
||||
padding: calc(var(--app-nav-height) + 1rem) 0 1rem 0;
|
||||
flex-direction: column;
|
||||
|
||||
.form,
|
||||
@@ -843,6 +880,10 @@ watch(customerCode, async (value) => {
|
||||
}
|
||||
}
|
||||
|
||||
.option-selector {
|
||||
margin: 1rem 0 1rem 1rem;
|
||||
}
|
||||
|
||||
.time-actions {
|
||||
gap: .5rem;
|
||||
display: flex;
|
||||
@@ -851,7 +892,6 @@ watch(customerCode, async (value) => {
|
||||
}
|
||||
|
||||
.edit-point-tip {
|
||||
color: #9a3412;
|
||||
padding: 0 1rem 1rem;
|
||||
font-size: .8125rem;
|
||||
margin-top: .25rem;
|
||||
|
||||
Reference in New Issue
Block a user