|
@@ -0,0 +1,306 @@
|
|
|
+<template>
|
|
|
+ <div class="p-8px bg-white">
|
|
|
+ <div class="px-4">
|
|
|
+ <BasicForm @register="registerForm">
|
|
|
+ <template #title1>
|
|
|
+ <TypographyTitle :level="4">包场时间</TypographyTitle>
|
|
|
+ <Divider></Divider>
|
|
|
+ </template>
|
|
|
+ <template #title2>
|
|
|
+ <TypographyTitle :level="4">封面、配套保险、使用须知</TypographyTitle>
|
|
|
+ <Divider></Divider>
|
|
|
+ </template>
|
|
|
+ <template #customer="{ model, field }">
|
|
|
+ <div v-for="(item, idx) in getCustomerList(model['categoryId'])" :key="item.value">
|
|
|
+ <Card class="my-4">
|
|
|
+ <FormItem :label="`${item.label}场地`" required :labelCol="{ xl: 2, sm: 3 }">
|
|
|
+ <InputNumber addon-before="共有" addon-after="个球场" v-model:value="model['inventory' + idx]"></InputNumber>
|
|
|
+ </FormItem>
|
|
|
+ <FormItem label="时间段及费用" required :labelCol="{ xl: 2, sm: 3 }" :wrapper-col="{ span: 22 }">
|
|
|
+ <ZtCustomTable :tableColumn="ScheduleArrangementColums" v-model:value="model[item.value]"></ZtCustomTable>
|
|
|
+ </FormItem>
|
|
|
+ </Card>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #title3>
|
|
|
+ <TypographyTitle :level="4">退款、预订限制</TypographyTitle>
|
|
|
+ <Divider></Divider>
|
|
|
+ </template>
|
|
|
+ <template #formFooter>
|
|
|
+ <div style="margin: 0 auto" class="w-full flex items-center justify-center">
|
|
|
+ <a-button type="primary" @click="save" class="mr-2" :loading="isSubmit"> 保存 </a-button>
|
|
|
+ <a-button type="error" @click="back" class="mr-2"> 关闭 </a-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </BasicForm>
|
|
|
+ <div class="h-20px"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup name="business-management-gymnasiumbag">
|
|
|
+ import { TypographyTitle, Divider, InputNumber, FormItem, Card, message } from 'ant-design-vue';
|
|
|
+ import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
|
|
|
+ import { getSprotProject, siteAdd } from '/@/api/common/api';
|
|
|
+ import { DemoOptionsItem } from '/@/api/demo/model/optionsModel';
|
|
|
+ import ZtCustomTable from '/@/components/ZtCustomTable/index.vue';
|
|
|
+ import { ScheduleArrangementColums, apiForm, priceRules } from './gymnasiumBag.data';
|
|
|
+ import { h, ref } from 'vue';
|
|
|
+ import { OriginalItem } from '/#/utils';
|
|
|
+ import { areAllItemsAllFieldsFilled } from '/@/utils';
|
|
|
+ import dayjs from 'dayjs';
|
|
|
+ import { useTabs } from '/@/hooks/web/useTabs';
|
|
|
+ const projectList = ref<DemoOptionsItem[]>([]);
|
|
|
+ const { close: closeTab } = useTabs();
|
|
|
+ const isSubmit = ref(false);
|
|
|
+ const formSchema: FormSchema[] = [
|
|
|
+ {
|
|
|
+ field: 'name',
|
|
|
+ label: '营业名称',
|
|
|
+ component: 'Select',
|
|
|
+ defaultValue: '111',
|
|
|
+ required: true,
|
|
|
+ labelWidth: 120,
|
|
|
+ colProps: {
|
|
|
+ span: 14,
|
|
|
+ xs: 24,
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ field: 'title1',
|
|
|
+ colSlot: 'title1',
|
|
|
+ label: '',
|
|
|
+ component: 'Input',
|
|
|
+ labelWidth: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'categoryId',
|
|
|
+ label: '球类项目',
|
|
|
+ component: 'CheckboxGroup',
|
|
|
+ defaultValue: [],
|
|
|
+ componentProps: {
|
|
|
+ options: projectList,
|
|
|
+ },
|
|
|
+ required: true,
|
|
|
+ labelWidth: 120,
|
|
|
+ colProps: {
|
|
|
+ span: 24,
|
|
|
+ xs: 24,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'customerInfo',
|
|
|
+ label: '球类项目',
|
|
|
+ component: 'CheckboxGroup',
|
|
|
+ colSlot: 'customer',
|
|
|
+ required: true,
|
|
|
+ labelWidth: 120,
|
|
|
+ colProps: {
|
|
|
+ span: 24,
|
|
|
+ xs: 24,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'title3',
|
|
|
+ colSlot: 'title3',
|
|
|
+ label: '',
|
|
|
+ component: 'Input',
|
|
|
+ labelWidth: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'earlyRefundTime',
|
|
|
+ label: '退款',
|
|
|
+ component: 'InputNumber',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ addonBefore: '开场前',
|
|
|
+ addonAfter: '分钟可退',
|
|
|
+ },
|
|
|
+ labelWidth: 120,
|
|
|
+ colProps: {
|
|
|
+ span: 24,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'buyLimit',
|
|
|
+ label: '预定限制',
|
|
|
+ component: 'InputNumber',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ addonBefore: '每笔订单最多可选择',
|
|
|
+ addonAfter: '场',
|
|
|
+ },
|
|
|
+ labelWidth: 120,
|
|
|
+ colProps: {
|
|
|
+ span: 24,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'reminder',
|
|
|
+ label: '温馨提示',
|
|
|
+ component: 'InputTextArea',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ autosize: {
|
|
|
+ minRows: 3,
|
|
|
+ maxRows: 6,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ defaultValue: '场地仅限个人使用,培训、比赛或者其他商业活动,可能需要额外付费。如有需求,请提前联系商家,咨询收费标准。',
|
|
|
+ labelWidth: 120,
|
|
|
+ colProps: {
|
|
|
+ span: 18,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const [registerForm, { setProps, resetFields, setFieldsValue, updateSchema, validate, getFieldsValue, appendSchemaByField }] = useForm({
|
|
|
+ schemas: formSchema,
|
|
|
+ showActionButtonGroup: false,
|
|
|
+ });
|
|
|
+ async function back() {
|
|
|
+ await closeTab();
|
|
|
+ }
|
|
|
+ async function save() {
|
|
|
+ const data = await getFieldsValue();
|
|
|
+ console.log(data);
|
|
|
+ return;
|
|
|
+ const form = await validate();
|
|
|
+
|
|
|
+ const cusotmValidate = await validateInventoryFields(form);
|
|
|
+ if (!cusotmValidate) {
|
|
|
+ return message.error('请填写必填项');
|
|
|
+ }
|
|
|
+ const newObj: apiForm = {
|
|
|
+ site: {
|
|
|
+ name: form.name,
|
|
|
+ categoryId: form.categoryId,
|
|
|
+ earlyRefundTime: form.earlyRefundTime,
|
|
|
+ buyLimit: form.buyLimit,
|
|
|
+ reminder: form.reminder,
|
|
|
+ type: 1, //0学校,1是体育馆
|
|
|
+ },
|
|
|
+ priceRulesList: getResultData(form),
|
|
|
+ };
|
|
|
+ isSubmit.value = true;
|
|
|
+ try {
|
|
|
+ await siteAdd(newObj);
|
|
|
+ await closeTab();
|
|
|
+ } catch (error) {
|
|
|
+ isSubmit.value = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ async function getProjectData() {
|
|
|
+ const res = await getSprotProject({ pageSize: 20 });
|
|
|
+ projectList.value = res.records.map((it) => {
|
|
|
+ return { value: it.id, label: it.name };
|
|
|
+ });
|
|
|
+ renderTable();
|
|
|
+ }
|
|
|
+ getProjectData();
|
|
|
+
|
|
|
+ function getCustomerList(list: string[]) {
|
|
|
+ const arr = projectList.value.filter((it) => {
|
|
|
+ return list.includes(it.value);
|
|
|
+ });
|
|
|
+ return arr;
|
|
|
+ }
|
|
|
+
|
|
|
+ async function renderTable() {
|
|
|
+ projectList.value.forEach(async (it, idx) => {
|
|
|
+ await appendSchemaByField(
|
|
|
+ {
|
|
|
+ field: it.value,
|
|
|
+ label: ``,
|
|
|
+ component: 'Select',
|
|
|
+ show: false,
|
|
|
+ defaultValue: [],
|
|
|
+ },
|
|
|
+
|
|
|
+ ''
|
|
|
+ );
|
|
|
+ await appendSchemaByField(
|
|
|
+ {
|
|
|
+ field: `inventory${idx}`,
|
|
|
+ label: ``,
|
|
|
+ component: 'Select',
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ ''
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function getResultData(form: any): priceRules[] {
|
|
|
+ const priceRulesList: any = [];
|
|
|
+ form.categoryId.split(',').map((it, idx) => {
|
|
|
+ const data = transformData(form[it]?.obj).map((item) => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ categoryId: it,
|
|
|
+ inventory: form[`inventory${idx}`],
|
|
|
+ type: 1, //0学校 1体育馆包场 2体育馆不固定场
|
|
|
+ };
|
|
|
+ });
|
|
|
+ priceRulesList.push(...data);
|
|
|
+ });
|
|
|
+ return priceRulesList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验 inventory 是否存在且 > 0
|
|
|
+ * @param formValues 表单数据
|
|
|
+ * @returns boolean 校验是否通过
|
|
|
+ */
|
|
|
+ function validateInventoryFields(formValues: any): boolean {
|
|
|
+ const { categoryId } = formValues;
|
|
|
+
|
|
|
+ if (!categoryId) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ const categoryIds = categoryId.split(',').map((id) => id.trim());
|
|
|
+
|
|
|
+ for (let i = 0; i < categoryIds.length; i++) {
|
|
|
+ const inventoryField = `inventory${i}`;
|
|
|
+ const inventoryValue = formValues[inventoryField];
|
|
|
+ const priceRulesList = formValues[categoryIds[i]];
|
|
|
+ if (inventoryValue === undefined || inventoryValue === null || inventoryValue <= 0 || !priceRulesList) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!areAllItemsAllFieldsFilled(priceRulesList.obj)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ type TransformedItem = {
|
|
|
+ dayOfWeek: string;
|
|
|
+ sellingPrice: number | null;
|
|
|
+ startTime: string;
|
|
|
+ endTime: string;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * 将原始数据转换为目标格式
|
|
|
+ * @param data - 原始数据数组
|
|
|
+ * @returns 转换后的数据数组
|
|
|
+ */
|
|
|
+ function transformData(data: OriginalItem[]): TransformedItem[] {
|
|
|
+ const result: TransformedItem[] = [];
|
|
|
+ for (const item of data) {
|
|
|
+ const { time = ['1', '2'] } = item;
|
|
|
+ for (let i = 1; i <= 7; i++) {
|
|
|
+ const key = `day${i}` as keyof OriginalItem;
|
|
|
+ const sellingPrice = item[key];
|
|
|
+ result.push({
|
|
|
+ dayOfWeek: `${i}`,
|
|
|
+ sellingPrice: sellingPrice === undefined ? null : sellingPrice,
|
|
|
+ startTime: dayjs(time[0]).format('YYYY-MM-DD hh:mm:ss'),
|
|
|
+ endTime: dayjs(time[1]).format('YYYY-MM-DD hh:mm:ss'),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+</script>
|