123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- <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]" :max="30" :min="1"></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" v-if="isMerchant">
- <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 { saveOrUpdate, queryById, Business } from './gymnasiumBag.api';
- import { computed, h, onUnmounted, ref, watch } from 'vue';
- import { OriginalItem } from '/#/utils';
- import { areAllItemsAllFieldsFilled, extractRefs } from '/@/utils';
- import dayjs from 'dayjs';
- import { useTabs } from '/@/hooks/web/useTabs';
- import { storeToRefs } from 'pinia';
- import { unref } from 'vue';
- const projectList = ref<DemoOptionsItem[]>([]);
- import { useUserStore } from '/@/store/modules/user';
- const { userInfo } = storeToRefs(useUserStore());
- const { close: closeTab } = useTabs();
- const isSubmit = ref(false);
- const uploadId = ref<any>();
- const isMerchant = computed(() => {
- return userInfo.value?.orgCode?.length > 3;
- });
- const changeData = ref(false);
- const formSchema: FormSchema[] = [
- {
- field: 'name',
- label: '营业名称',
- component: 'Select',
- required: true,
- labelWidth: 120,
- componentProps: {
- // api: Business,
- // params: {
- // orgCode: useUserStore().userInfo?.orgCode,
- // },
- // immediate: false,
- // valueField: 'id',
- // labelField: 'name',
- onChange(e) {
- getQueryData(e);
- changeData.value = true;
- },
- disabled: isMerchant.value,
- },
- colProps: {
- span: 14,
- xs: 24,
- },
- },
- {
- field: 'title1',
- colSlot: 'title1',
- label: '',
- component: 'Input',
- labelWidth: 0,
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- {
- field: 'categoryId',
- label: '球类项目',
- component: 'CheckboxGroup',
- defaultValue: [],
- componentProps: {
- options: projectList,
- },
- required: true,
- labelWidth: 120,
- colProps: {
- span: 24,
- xs: 24,
- },
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- {
- field: 'customerInfo',
- label: '球类项目',
- component: 'CheckboxGroup',
- colSlot: 'customer',
- required: true,
- labelWidth: 120,
- colProps: {
- span: 24,
- xs: 24,
- },
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- {
- field: 'title3',
- colSlot: 'title3',
- label: '',
- component: 'Input',
- labelWidth: 0,
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- {
- field: 'earlyRefundTime',
- label: '退款',
- component: 'InputNumber',
- required: true,
- componentProps: {
- addonBefore: '开场前',
- addonAfter: '分钟可退',
- },
- labelWidth: 120,
- colProps: {
- span: 24,
- },
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- {
- field: 'buyLimit',
- label: '预定限制',
- component: 'InputNumber',
- required: true,
- componentProps: {
- addonBefore: '每笔订单最多可选择',
- addonAfter: '场',
- },
- labelWidth: 120,
- colProps: {
- span: 24,
- },
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- {
- field: 'reminder',
- label: '温馨提示',
- component: 'InputTextArea',
- required: true,
- componentProps: {
- autosize: {
- minRows: 3,
- maxRows: 6,
- },
- },
- defaultValue: '场地仅限个人使用,培训、比赛或者其他商业活动,可能需要额外付费。如有需求,请提前联系商家,咨询收费标准。',
- labelWidth: 120,
- colProps: {
- span: 18,
- },
- ifShow() {
- return isMerchant.value || changeData.value;
- },
- },
- ];
- const [registerForm, { setProps, resetFields, setFieldsValue, updateSchema, validate, getFieldsValue, appendSchemaByField }] = useForm({
- schemas: formSchema,
- showActionButtonGroup: false,
- });
- const isUpdate = ref(false);
- async function back() {
- await closeTab();
- }
- async function getQueryData(id) {
- const res = await queryById({ siteId: id });
- if (!res.appSitePlaceCuDTO || !res.appSiteCategoryRuleDTOS) {
- isUpdate.value = false;
- } else {
- isUpdate.value = true;
- const categoryIdList = res.appSiteCategoryRuleDTOS.map((it) => it.categoryId);
- const newDATA: any = [];
- const categoryId: any = [];
- res.appSiteCategoryRuleDTOS.map((it) => {
- newDATA.push(
- ...it.appSiteRuleTimeFormDTOList.map((its) => {
- categoryId.push({ [it.categoryId]: its.id });
- return { ...reverseTransformData([...its.appSiteRuleDTOList]) };
- })
- );
- });
- const filed = {
- categoryId: categoryIdList,
- buyLimit: res.appSitePlaceCuDTO.buyLimit,
- earlyRefundTime: res.appSitePlaceCuDTO.earlyRefundTime,
- reminder: res.appSitePlaceCuDTO.reminder,
- };
- const newData = mergeSameKeys(newDATA);
- uploadId.value = mergeSameKeysIds(categoryId);
- categoryIdList.forEach((it, idx) => {
- filed[it] = newData[it];
- filed[`inventory${idx}`] = res.appSiteCategoryRuleDTOS[idx].count;
- });
- setFieldsValue(filed);
- }
- }
- async function getBusinessData() {
- const res = await Business({ orgCode: userInfo.value?.orgCode });
- updateSchema({ field: 'name', componentProps: { options: res.map((it) => ({ label: it.name, value: it.id })) } });
- //如果商家端进入默认取第一个
- setFieldsValue({
- name: res[0].id,
- });
- getQueryData(res[0].id);
- }
- getBusinessData();
- async function save() {
- const form = await getFieldsValue();
- await validate();
- if (!validateInventoryFields(form)) return message.error('请填写完整包场时间');
- const categoryList = form.categoryId.split(',');
- const newObj = {
- appSitePlaceCuDTO: {
- buyLimit: form.buyLimit,
- earlyRefundTime: form.earlyRefundTime,
- reminder: form.reminder,
- siteId: form.name,
- },
- appSiteCategoryRuleDTOS: categoryList.map((it, idx) => {
- const appSiteRuleTimeFormDTOList = form[it].map((items) => extractRefs(items.editValueRefs));
- return {
- categoryId: it,
- count: form[`inventory${idx}`],
- appSiteRuleTimeFormDTOList: appSiteRuleTimeFormDTOList.map((formDtoList, index) => {
- return {
- id: uploadId.value ? uploadId.value[it][index] : null,
- startTime: formDtoList.time[0],
- endTime: formDtoList.time[1],
- appSiteRuleDTOList: transformData([appSiteRuleTimeFormDTOList[index]], it),
- };
- }),
- };
- }),
- };
- isSubmit.value = true;
- // return;
- try {
- await saveOrUpdate(newObj, isUpdate.value);
- isSubmit.value = false;
- 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,
- },
- ''
- );
- });
- }
- type TransformedItem = {
- dayOfWeek: string;
- sellingPrice: number | null;
- startTime: string;
- endTime: string;
- categoryId: string;
- batchuuid?: string;
- };
- /**
- * 将原始数据转换为目标格式
- * @param data - 原始数据数组
- * @returns 转换后的数据数组
- */
- function transformData(data: OriginalItem[], categoryId: string): 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: any = item[key];
- result.push({
- dayOfWeek: `${i}`,
- sellingPrice: sellingPrice,
- startTime: time[0],
- endTime: time[1],
- categoryId,
- // sitePlaceId,
- batchuuid: item[`dayId${i}`],
- });
- }
- }
- return result;
- }
- /**
- * 校验 inventory 是否存在且 > 0
- * @param formValues 表单数据
- * @returns boolean 校验是否通过
- */
- function validateInventoryFields(formValues: any): boolean {
- const { categoryId } = formValues;
- if (!categoryId) {
- return false;
- }
- const categoryIds = categoryId.split(',');
- 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;
- }
- const priceRulesListIsValid = priceRulesList.map((it) => it.editValueRefs);
- if (!areAllItemsAllFieldsFilled(priceRulesListIsValid)) {
- return false;
- }
- }
- return true;
- }
- function reverseTransformData(transformedData: TransformedItem[]): Record<string, OriginalItem[]> {
- const groupedByTime: Record<string, TransformedItem[]> = {};
- console.log(transformedData, 'transformedData');
- // 首先按时间分组数据
- transformedData.forEach((item) => {
- const timeKey = `${item.startTime}-${item.endTime}`;
- if (!groupedByTime[timeKey]) {
- groupedByTime[timeKey] = [];
- }
- groupedByTime[timeKey].push(item);
- });
- // 构造结果对象
- const result: Record<string, OriginalItem[]> = {};
- Object.keys(groupedByTime).forEach((timeKey) => {
- const items = groupedByTime[timeKey];
- const [startTime, endTime] = timeKey.split('-');
- // 按照 categoryId 分组
- const groupedByCategory: Record<string, TransformedItem[]> = {};
- items.forEach((item) => {
- if (!groupedByCategory[item.categoryId]) {
- groupedByCategory[item.categoryId] = [];
- }
- groupedByCategory[item.categoryId].push(item);
- });
- // 为每个 categoryId 创建原始数据项
- Object.keys(groupedByCategory).forEach((categoryId) => {
- if (!result[categoryId]) {
- result[categoryId] = [];
- }
- const categoryItems = groupedByCategory[categoryId];
- const originalItem: OriginalItem = {
- time: [startTime, endTime],
- };
- // 添加每天的价格信息
- categoryItems.forEach((item) => {
- const dayKey = `day${item.dayOfWeek}` as keyof OriginalItem;
- originalItem[dayKey] = Number(item.sellingPrice);
- });
- result[categoryId].push(originalItem);
- });
- });
- return result;
- }
- function mergeSameKeys(data: Record<string, any[]>[]): Record<string, any[]> {
- const result: Record<string, any[]> = {};
- data.forEach((item) => {
- Object.keys(item).forEach((key) => {
- if (!result[key]) {
- result[key] = [];
- }
- // 合并数组
- result[key] = [...result[key], ...item[key]];
- });
- });
- return result;
- }
- function mergeSameKeysIds(data: Record<string, string>[]): Record<string, string[]> {
- const result: Record<string, string[]> = {};
- data.forEach((item) => {
- Object.keys(item).forEach((key) => {
- if (!result[key]) {
- result[key] = [];
- }
- result[key].push(item[key]);
- });
- });
- return result;
- }
- </script>
|