add package
This commit is contained in:
@@ -25,6 +25,15 @@
|
||||
<t-form-item v-if="isGlobalManager" label="门店" :arrow="isCreateMode" @click="openStorePicker">
|
||||
<div class="picker-text" v-text="selectedStoreName" />
|
||||
</t-form-item>
|
||||
<t-form-item label="业务类型" :arrow="isCreateMode" @click="isCreateMode && openBizTypePicker()">
|
||||
<div class="picker-text" v-text="getBizTypeText(formModel.bizType)" />
|
||||
</t-form-item>
|
||||
<div v-if="formModel.bizType === 'PACKAGE_PURCHASE'" class="biz-type-tip">
|
||||
套餐购买事件必须绑定一个套餐配置。实际购买时只能使用此处绑定的套餐,不能临时更换。
|
||||
</div>
|
||||
<t-form-item v-if="formModel.bizType === 'PACKAGE_PURCHASE'" label="绑定套餐" required-mark arrow @click="openPackageConfigPicker">
|
||||
<div class="picker-text" v-text="selectedPackageConfig?.name || '请选择套餐配置'" />
|
||||
</t-form-item>
|
||||
<t-form-item label="说明">
|
||||
<t-textarea
|
||||
class="description"
|
||||
@@ -80,7 +89,7 @@
|
||||
<t-switch v-model="formModel.requirePhoto" />
|
||||
</t-form-item>
|
||||
<t-form-item label="需要核销" content-align="right">
|
||||
<t-switch v-model="formModel.requireVerification" />
|
||||
<t-switch v-model="formModel.requireVerification" :disabled="formModel.bizType === 'PACKAGE_PURCHASE'" />
|
||||
</t-form-item>
|
||||
<t-form-item label="状态" arrow @click="openStatusPicker">
|
||||
<div class="picker-text" v-text="getStatusText(formModel.status)" />
|
||||
@@ -157,6 +166,24 @@
|
||||
@confirm="confirmStorePicker"
|
||||
/>
|
||||
</t-popup>
|
||||
<t-popup v-model="bizTypePickerVisible" placement="bottom">
|
||||
<t-picker
|
||||
v-model="bizTypePickerDraft"
|
||||
:columns="bizTypePickerColumns"
|
||||
title="业务类型"
|
||||
@cancel="bizTypePickerVisible = false"
|
||||
@confirm="confirmBizTypePicker"
|
||||
/>
|
||||
</t-popup>
|
||||
<t-popup v-model="packageConfigPickerVisible" placement="bottom">
|
||||
<t-picker
|
||||
v-model="packageConfigPickerDraft"
|
||||
:columns="packageConfigPickerColumns"
|
||||
title="绑定套餐"
|
||||
@cancel="packageConfigPickerVisible = false"
|
||||
@confirm="confirmPackageConfigPicker"
|
||||
/>
|
||||
</t-popup>
|
||||
<t-popup v-model="statusPickerVisible" placement="bottom">
|
||||
<t-picker
|
||||
v-model="statusPickerDraft"
|
||||
@@ -219,12 +246,16 @@ import { Time } from "timi-web";
|
||||
import { type ModuleCode, type Role, RoleAPI, useUserStore } from "timi-web-api";
|
||||
import type { ColorObject } from "tdesign-mobile-vue";
|
||||
import EventAPI from "@/api/EventAPI";
|
||||
import PackageAPI from "@/api/PackageAPI";
|
||||
import EventOptionEditor from "@/pages/event/component/EventOptionEditor.vue";
|
||||
import { useCurrentStoreStore } from "@/store/currentStoreStore";
|
||||
import { useNavBarStore } from "@/store/navBarStore";
|
||||
import type { EventItem, EventLimitType, EventOptionGroup, EventStatus, EventValueType, EventValueUnit } from "@/types/EventItem";
|
||||
import type { EventBizType, EventItem, EventLimitType, EventOptionGroup, EventStatus, EventValueType, EventValueUnit } from "@/types/EventItem";
|
||||
import type { GaoPackageConfig } from "@/types/Package";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
import { normalizeEventOptionGroupList, prepareEventOptionGroupList, validateEventOptionGroupList } from "@/utils/eventOption";
|
||||
import { getEventBizTypeText } from "@/utils/event";
|
||||
import { getPackageConfigStatusText } from "@/utils/package";
|
||||
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||
import { Message } from "@/utils/message";
|
||||
|
||||
@@ -263,6 +294,8 @@ const optionGroupList = ref<EventOptionGroup[]>([]);
|
||||
const formModel = reactive({
|
||||
id: "",
|
||||
storeId: "",
|
||||
bizType: "GENERAL" as EventBizType,
|
||||
packageConfigId: "",
|
||||
name: "",
|
||||
description: "",
|
||||
color: "#0f766e",
|
||||
@@ -279,6 +312,93 @@ const formModel = reactive({
|
||||
roleCodeList: [] as string[]
|
||||
});
|
||||
|
||||
// ---------- 业务类型 ----------
|
||||
|
||||
const bizTypeOptions: Array<{ label: string; value: EventBizType }> = [
|
||||
{ label: "普通登记", value: "GENERAL" },
|
||||
{ label: "套餐购买", value: "PACKAGE_PURCHASE" }
|
||||
];
|
||||
const bizTypePickerVisible = ref(false);
|
||||
const bizTypePickerDraft = ref<PickerValue[]>([formModel.bizType]);
|
||||
const bizTypePickerColumns = [bizTypeOptions];
|
||||
|
||||
function getBizTypeText(value: EventBizType): string {
|
||||
return getEventBizTypeText(value);
|
||||
}
|
||||
|
||||
function openBizTypePicker(): void {
|
||||
if (!isCreateMode.value) {
|
||||
return;
|
||||
}
|
||||
bizTypePickerDraft.value = [formModel.bizType];
|
||||
bizTypePickerVisible.value = true;
|
||||
}
|
||||
|
||||
async function confirmBizTypePicker(value: Array<string | number>): Promise<void> {
|
||||
const bizType = value[0];
|
||||
if (bizType !== "GENERAL" && bizType !== "PACKAGE_PURCHASE") {
|
||||
return;
|
||||
}
|
||||
formModel.bizType = bizType;
|
||||
if (bizType === "PACKAGE_PURCHASE") {
|
||||
formModel.requireVerification = false;
|
||||
await loadPackageConfigList();
|
||||
} else {
|
||||
formModel.packageConfigId = "";
|
||||
}
|
||||
bizTypePickerVisible.value = false;
|
||||
}
|
||||
|
||||
// ---------- 套餐绑定 ----------
|
||||
|
||||
const packageConfigList = ref<GaoPackageConfig[]>([]);
|
||||
const packageConfigPickerVisible = ref(false);
|
||||
const packageConfigPickerDraft = ref<PickerValue[]>([]);
|
||||
const packageConfigPickerColumns = computed(() => [[...packageConfigList.value].map(item => ({
|
||||
label: `${item.name || "未命名套餐"}(${getPackageConfigStatusText(item.status)})`,
|
||||
value: item.id || ""
|
||||
}))]);
|
||||
const selectedPackageConfig = computed(() => packageConfigList.value.find(item => item.id === formModel.packageConfigId));
|
||||
|
||||
async function loadPackageConfigList(): Promise<void> {
|
||||
if (formModel.bizType !== "PACKAGE_PURCHASE" || !formModel.storeId) {
|
||||
packageConfigList.value = [];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = await PackageAPI.configList({
|
||||
storeId: formModel.storeId,
|
||||
index: 0,
|
||||
size: 1000
|
||||
});
|
||||
packageConfigList.value = result.list || [];
|
||||
} catch (error) {
|
||||
packageConfigList.value = [];
|
||||
Message.error(getErrorMessage(error, "套餐配置加载失败"));
|
||||
}
|
||||
}
|
||||
|
||||
function openPackageConfigPicker(): void {
|
||||
if (formModel.bizType !== "PACKAGE_PURCHASE") {
|
||||
return;
|
||||
}
|
||||
if (!packageConfigList.value.length) {
|
||||
Message.warning("当前门店没有可绑定的套餐配置");
|
||||
return;
|
||||
}
|
||||
packageConfigPickerDraft.value = [formModel.packageConfigId];
|
||||
packageConfigPickerVisible.value = true;
|
||||
}
|
||||
|
||||
function confirmPackageConfigPicker(value: Array<string | number>): void {
|
||||
const packageConfigId = String(value[0] || "");
|
||||
if (!packageConfigList.value.some(item => item.id === packageConfigId)) {
|
||||
return;
|
||||
}
|
||||
formModel.packageConfigId = packageConfigId;
|
||||
packageConfigPickerVisible.value = false;
|
||||
}
|
||||
|
||||
// ---------- 门店选择 ----------
|
||||
|
||||
const storePickerVisible = ref(false);
|
||||
@@ -309,13 +429,16 @@ function openStorePicker(): void {
|
||||
storePickerVisible.value = true;
|
||||
}
|
||||
|
||||
function confirmStorePicker(): void {
|
||||
async function confirmStorePicker(): Promise<void> {
|
||||
const storeId = String(storePickerDraft.value[0] || "");
|
||||
if (!storeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
formModel.storeId = storeId;
|
||||
if (formModel.bizType === "PACKAGE_PURCHASE") {
|
||||
await loadPackageConfigList();
|
||||
}
|
||||
storePickerVisible.value = false;
|
||||
}
|
||||
|
||||
@@ -573,6 +696,10 @@ function validateForm(): boolean {
|
||||
Message.warning("请至少选择一个可登记角色");
|
||||
return false;
|
||||
}
|
||||
if (formModel.bizType === "PACKAGE_PURCHASE" && (!formModel.packageConfigId || !selectedPackageConfig.value)) {
|
||||
Message.warning("请选择绑定套餐配置");
|
||||
return false;
|
||||
}
|
||||
const optionError = validateEventOptionGroupList(optionGroupList.value);
|
||||
if (optionError) {
|
||||
Message.warning(optionError);
|
||||
@@ -582,6 +709,10 @@ function validateForm(): boolean {
|
||||
Message.warning("请输入有效的约束数值");
|
||||
return false;
|
||||
}
|
||||
if (formModel.bizType === "PACKAGE_PURCHASE" && formModel.requireVerification) {
|
||||
Message.warning("套餐购买事件不能要求核销");
|
||||
return false;
|
||||
}
|
||||
const beginAt = resolveTimestamp(formModel.beginAtText);
|
||||
const endAt = resolveTimestamp(formModel.endAtText);
|
||||
if (beginAt !== undefined && endAt !== undefined && endAt < beginAt) {
|
||||
@@ -636,6 +767,8 @@ async function saveEventItem(): Promise<void> {
|
||||
const payload: EventItem = {
|
||||
id: formModel.id || undefined,
|
||||
storeId: formModel.storeId,
|
||||
bizType: formModel.bizType,
|
||||
packageConfigId: formModel.bizType === "PACKAGE_PURCHASE" ? formModel.packageConfigId : undefined,
|
||||
name: formModel.name.trim(),
|
||||
description: formModel.description,
|
||||
color: formModel.color,
|
||||
@@ -698,6 +831,8 @@ async function fillForm(): Promise<void> {
|
||||
Object.assign(formModel, {
|
||||
id: current.id || "",
|
||||
storeId: current.storeId || formModel.storeId,
|
||||
bizType: current.bizType || "GENERAL",
|
||||
packageConfigId: current.packageConfigId || "",
|
||||
name: current.name || "",
|
||||
description: current.description || "",
|
||||
color: current.color || "#2f88ff",
|
||||
@@ -712,6 +847,12 @@ async function fillForm(): Promise<void> {
|
||||
endAtText: current.endAt ? Time.toDateTime(current.endAt) : "",
|
||||
roleCodeList: [...(current.roleCodeList || [])]
|
||||
});
|
||||
if (formModel.bizType === "PACKAGE_PURCHASE") {
|
||||
await loadPackageConfigList();
|
||||
if (current.packageConfig && !packageConfigList.value.some(item => item.id === current.packageConfig?.id)) {
|
||||
packageConfigList.value.unshift(current.packageConfig);
|
||||
}
|
||||
}
|
||||
optionGroupList.value = normalizeEventOptionGroupList(current.optionGroupList);
|
||||
formModel.limitValueText = resolveLimitValueText(current.limitValue);
|
||||
colorDraft.value = formModel.color;
|
||||
@@ -762,6 +903,14 @@ onUnmounted(() => navBarStore.clearRight());
|
||||
font-size: .875rem;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.biz-type-tip {
|
||||
padding: .75rem 1rem;
|
||||
color: var(--td-text-color-secondary);
|
||||
font-size: .8125rem;
|
||||
line-height: 1.5;
|
||||
background: var(--td-bg-color-secondarycontainer);
|
||||
}
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
|
||||
Reference in New Issue
Block a user