add point
This commit is contained in:
@@ -8,9 +8,9 @@
|
||||
readonly
|
||||
borderless
|
||||
placeholder="选择或扫码客户"
|
||||
@click="openSelectedCustomerList"
|
||||
@click="!isEditMode && openSelectedCustomerList()"
|
||||
>
|
||||
<template #suffix-icon>
|
||||
<template v-if="!isEditMode" #suffix-icon>
|
||||
<div class="actions">
|
||||
<t-button
|
||||
theme="primary"
|
||||
@@ -47,9 +47,20 @@
|
||||
v-model="selectedEventIdList"
|
||||
class="registration-event-selector"
|
||||
:event-list="eventList"
|
||||
:disabled="isEditMode"
|
||||
required-mark
|
||||
/>
|
||||
<t-form-item label="登记时间" content-align="right">
|
||||
<div v-if="isEditMode" class="edit-point-tip">已产生积分的登记记录不会因修改客户、事件或时间而重算;如需修改这些事实,请删除后重新创建。</div>
|
||||
<t-form-item v-if="showSourceValueInput" label="自定义积分" required-mark>
|
||||
<t-input
|
||||
v-model.trim="pointValueText"
|
||||
type="number"
|
||||
align="right"
|
||||
borderless
|
||||
:placeholder="sourceValuePlaceholder"
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item v-if="!isEditMode" label="登记时间" content-align="right">
|
||||
<div class="time-actions">
|
||||
<t-button
|
||||
theme="primary"
|
||||
@@ -68,6 +79,9 @@
|
||||
/>
|
||||
</div>
|
||||
</t-form-item>
|
||||
<t-form-item v-else label="登记时间" content-align="right">
|
||||
<span class="readonly-time" v-text="registeredAtText || '此刻'" />
|
||||
</t-form-item>
|
||||
<t-form-item label="登记备注">
|
||||
<t-textarea
|
||||
v-model.trim="note"
|
||||
@@ -103,6 +117,7 @@
|
||||
</t-cell-group>
|
||||
<div v-else class="empty">当前客户暂无事件记录</div>
|
||||
<customer-selector
|
||||
v-if="!isEditMode"
|
||||
v-model="selectedCustomerIdList"
|
||||
v-model:visible="selectorVisible"
|
||||
:selection-mode="isEditMode ? 'single' : 'multiple'"
|
||||
@@ -151,7 +166,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { AttachmentAPI, Time, type Attachment } from "timi-web";
|
||||
import { AttachmentAPI, Time, type Attachment, useUserStore } from "timi-web";
|
||||
import { Toast } from "tdesign-mobile-vue";
|
||||
import CustomerAPI from "@/api/CustomerAPI";
|
||||
import EventAPI from "@/api/EventAPI";
|
||||
@@ -168,6 +183,7 @@ import type { EventItem } from "@/types/EventItem";
|
||||
import type { EventRecord } from "@/types/EventRecord";
|
||||
import { getEventRecordPhotoURL } from "@/utils/eventRecord";
|
||||
import { permissionCodes } from "@/utils/permission";
|
||||
import { loadSourceValueRange } from "@/utils/point";
|
||||
import { compressUploadImageList } from "@/utils/imageCompression";
|
||||
|
||||
defineOptions({
|
||||
@@ -177,6 +193,7 @@ defineOptions({
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const settingStore = useSettingStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
type EditablePhoto = {
|
||||
attachment?: Partial<Attachment>;
|
||||
@@ -375,6 +392,45 @@ function appendRecordEvent(record: EventRecord): void {
|
||||
eventList.value = [record.event, ...eventList.value];
|
||||
}
|
||||
|
||||
// ---------- 积分规则联动 ----------
|
||||
|
||||
const pointValueText = ref("");
|
||||
const sourceValueRange = ref<[number, number]>();
|
||||
let sourceValueLoadToken = 0;
|
||||
|
||||
const showSourceValueInput = computed(() => (
|
||||
!isEditMode.value
|
||||
&& userStore.hasPermissions(permissionCodes.point.sourceValue)
|
||||
&& !!sourceValueRange.value
|
||||
));
|
||||
const sourceValuePlaceholder = computed(() => {
|
||||
const range = sourceValueRange.value;
|
||||
return range ? `请输入 ${range[0]}-${range[1]} 的正整数` : "请输入积分";
|
||||
});
|
||||
|
||||
async function loadSourceValueRule(): Promise<void> {
|
||||
const token = sourceValueLoadToken + 1;
|
||||
sourceValueLoadToken = token;
|
||||
sourceValueRange.value = undefined;
|
||||
if (isEditMode.value || !userStore.hasPermissions(permissionCodes.point.sourceValue) || !selectedEventIdList.value.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sourceValueRange.value = await loadSourceValueRange(selectedEventIdList.value);
|
||||
if (token !== sourceValueLoadToken) {
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
sourceValueRange.value = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSourceValue(): number | undefined {
|
||||
const value = Number(pointValueText.value);
|
||||
return Number.isSafeInteger(value) && 0 < value ? value : undefined;
|
||||
}
|
||||
|
||||
// ---------- 照片 ----------
|
||||
|
||||
const recordPhotoInputRef = ref<HTMLInputElement>();
|
||||
@@ -484,6 +540,7 @@ async function submitRecord(): Promise<void> {
|
||||
customerIdList,
|
||||
remark: note.value || "客户现场登记",
|
||||
registeredAt: buildRegisteredAt(),
|
||||
pointValue: showSourceValueInput.value ? resolveSourceValue() : undefined,
|
||||
attachmentList: buildTempFileIdList().map(tempFileId => ({
|
||||
tempFileId,
|
||||
attachType: "PHOTO"
|
||||
@@ -493,6 +550,7 @@ async function submitRecord(): Promise<void> {
|
||||
selectedCustomerList.value = [];
|
||||
selectedCustomerIdList.value = [];
|
||||
note.value = "";
|
||||
pointValueText.value = "";
|
||||
photoItemList.value = [];
|
||||
await loadRecentRecordList();
|
||||
await settingStore.playRegisterSuccessSound();
|
||||
@@ -512,23 +570,30 @@ function validateForm(): boolean {
|
||||
Toast.warning("请至少选择一个登记事件");
|
||||
return false;
|
||||
}
|
||||
if (showSourceValueInput.value) {
|
||||
const pointValue = resolveSourceValue();
|
||||
const range = sourceValueRange.value;
|
||||
if (!pointValue || !range || pointValue < range[0] || range[1] < pointValue) {
|
||||
Toast.warning(`自定义积分必须是 ${range?.[0] || 1}-${range?.[1] || 0} 的正整数`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function updateRecord(): Promise<void> {
|
||||
const submitCustomer = selectedCustomer.value;
|
||||
if (!editingRecord.value?.id || !submitCustomer?.id) {
|
||||
if (!editingRecord.value?.id || !editingRecord.value.customerId || !editingRecord.value.eventId) {
|
||||
Toast.warning("登记事件记录不存在");
|
||||
return;
|
||||
}
|
||||
|
||||
await EventRecordAPI.update({
|
||||
...editingRecord.value,
|
||||
customerId: submitCustomer.id,
|
||||
eventId: selectedEventIdList.value[0],
|
||||
customerId: editingRecord.value.customerId,
|
||||
eventId: editingRecord.value.eventId,
|
||||
remark: note.value,
|
||||
registeredAt: buildRegisteredAt(),
|
||||
registeredAt: editingRecord.value.registeredAt,
|
||||
attachmentList: buildPhotoAttachmentList()
|
||||
});
|
||||
Toast.success("记录已保存");
|
||||
@@ -574,6 +639,7 @@ async function loadRecordForEdit(): Promise<void> {
|
||||
selectedEventIdList.value = record.eventId ? [record.eventId] : [];
|
||||
registeredAtText.value = record.registeredAt ? Time.formatDateTime(new Date(record.registeredAt)) : "";
|
||||
note.value = record.remark || "";
|
||||
pointValueText.value = "";
|
||||
photoItemList.value = (record.attachmentList || [])
|
||||
.filter(item => item.attachType === "PHOTO" || !item.attachType)
|
||||
.filter(item => !!item.id)
|
||||
@@ -586,6 +652,10 @@ async function loadRecordForEdit(): Promise<void> {
|
||||
|
||||
onMounted(loadPageData);
|
||||
|
||||
watch(selectedEventIdList, async () => {
|
||||
await loadSourceValueRule();
|
||||
}, { deep: true });
|
||||
|
||||
watch(customerCode, async (value) => {
|
||||
if (!value) {
|
||||
return;
|
||||
@@ -647,6 +717,17 @@ watch(customerCode, async (value) => {
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.edit-point-tip {
|
||||
color: #9a3412;
|
||||
padding: 0 1rem 1rem;
|
||||
font-size: .8125rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.readonly-time {
|
||||
color: #52607a;
|
||||
}
|
||||
}
|
||||
|
||||
.record-photo {
|
||||
@@ -730,6 +811,11 @@ watch(customerCode, async (value) => {
|
||||
.selector-action {
|
||||
color: #93c5fd;
|
||||
}
|
||||
|
||||
.edit-point-tip,
|
||||
.readonly-time {
|
||||
color: #fbbf24;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user