diff --git a/src/hooks/useProductsSets.js b/src/hooks/useProductsSets.js index 07c68ad..a4ec80a 100644 --- a/src/hooks/useProductsSets.js +++ b/src/hooks/useProductsSets.js @@ -129,7 +129,7 @@ export const useProductsTypesFieldsets = (type) => { export const useNewProductRecord = () => { return { info: { - 'id': null, + 'id': '', 'title': '', 'code': '', 'product_type_id': '', @@ -139,43 +139,43 @@ export const useNewProductRecord = () => { 'duration_unit': 'h', 'open_weekdays': '', 'recommends_rate': 0, + 'dept': '', 'dept_id': 0, 'dept_name': '', 'display_to_c': 0, 'km': 0, 'city_id': 0, 'city_name': '', - }, - default_lgc: { - 'title': '', - 'description': '', - 'lgc': 1, - 'id': null, - }, - default_quotation: { - 'id': null, - 'adult_cost': 0, - 'child_cost': 0, - 'currency': 'CNY', - 'unit_id': '1', - 'unit_name': '每团', - 'group_size_min': 1, - 'group_size_max': 2, - 'use_dates_start': '', - 'use_dates_end': '', - 'weekdays': '', - 'audit_state_id': -1, - 'audit_state_name': '', + 'open_hours': '', 'lastedit_changed': '', + 'create_date': '', + 'created_by': '', }, lgc_details: [ { 'title': '', 'description': '', 'lgc': 1, - 'id': null, + 'id': '', + }, + ], + quotation: [ + { + 'id': '', + 'adult_cost': 0, + 'child_cost': 0, + 'currency': 'CNY', + 'unit_id': '1', + 'unit_name': '每团', + 'group_size_min': 1, + 'group_size_max': 2, + 'use_dates_start': '', + 'use_dates_end': '', + 'weekdays': '', + 'audit_state_id': -1, + 'audit_state_name': '', + 'lastedit_changed': '', }, ], - quotation: [], }; }; diff --git a/src/stores/Products/Index.js b/src/stores/Products/Index.js index 1b7c10b..03e1c00 100644 --- a/src/stores/Products/Index.js +++ b/src/stores/Products/Index.js @@ -95,7 +95,7 @@ export const postProductsAuditAction = async (auditState, infoRow) => { // return errcode !== 0 ? {} : result; }; -export const postProductsSave = async (products) => { +export const postProductsSaveAction = async (products) => { const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_save`, products); return { errcode, result }; } diff --git a/src/views/products/Detail/ProductInfo.jsx b/src/views/products/Detail/ProductInfo.jsx index 161a642..70fe148 100644 --- a/src/views/products/Detail/ProductInfo.jsx +++ b/src/views/products/Detail/ProductInfo.jsx @@ -1,35 +1,51 @@ import { createContext, useEffect, useState } from 'react'; -import { Breadcrumb, Form, Divider, Button, Input, Select, Row, Col } from 'antd'; +import { App, Breadcrumb, Form, Divider, Button, Input, Select, Row, Col } from 'antd'; import { useTranslation } from 'react-i18next'; -import { useProductsTypesMapVal, } from '@/hooks/useProductsSets'; -import useProductsStore, { postProductsSave } from '@/stores/Products/Index'; +import { useProductsTypesMapVal, useNewProductRecord } from '@/hooks/useProductsSets'; +import useProductsStore, { postProductsSaveAction } from '@/stores/Products/Index'; import useAuthStore from '@/stores/Auth'; import RequireAuth from '@/components/RequireAuth'; -import { PERM_PRODUCTS_MANAGEMENT, PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFER_PUT } from '@/config'; +import { PERM_PRODUCTS_MANAGEMENT, PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFER_PUT, } from '@/config'; import DeptSelector from '@/components/DeptSelector'; import CitySelector from '@/components/CitySelector'; import { at, isEmpty, pick } from '@/utils/commons'; import ProductInfoForm from './ProductInfoForm'; +import dayjs from 'dayjs'; +import { usingStorage } from '@/hooks/usingStorage' const ProductInfo = ({ editable, ...props }) => { const { t } = useTranslation(); + const { notification, message } = App.useApp(); + const { userId } = usingStorage() const isPermitted = useAuthStore((state) => state.isPermitted); const productsTypesMapVal = useProductsTypesMapVal(); - const [activeAgency, agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.activeAgency, state.agencyProducts, state.editingProduct, state.setEditingProduct]); + const newProduct = useNewProductRecord(); - const onSave = (err, values, forms) => { + const [loading, setLoading, ] = useProductsStore((state) => [state.loading, state.setLoading]); + const [activeAgency, agencyProducts, editingProduct, ] = useProductsStore((state) => [state.activeAgency, state.agencyProducts, state.editingProduct, ]); + + const onSave = async (err, values, forms) => { values.travel_agency_id = activeAgency.travel_agency_id; - const poster = { + const copyNewProduct = structuredClone(newProduct); + const poster = { "audit_state": "-1", - // "create_date": "", - // "created_by": "", + // "create_date": dayjs().format('YYYY-MM-DD HH:mm:ss'), + // "created_by": userId, "travel_agency_id": activeAgency.travel_agency_id, // "travel_agency_name": "", // "lastedit_changed": "", }; const copyFields = pick(editingProduct.info, ['title', 'product_type_id', ]); - const readyToSubInfo = {...values.info, ...copyFields, type: copyFields.product_type_id, ...poster }; - console.log('onSave', editingProduct.info, readyToSubInfo); + const readyToSubInfo = {...copyNewProduct.info, ...values.info, ...copyFields, type: copyFields.product_type_id, ...poster }; + // console.log('onSave', editingProduct.info, readyToSubInfo); + const prevLgcDetailsMapped = editingProduct.lgc_details.reduce((r, c) => ({...r, [c.lgc]: {...c, description: c.descriptions}}), {}); // todo: description字段不一致 + const mergedLgc = { ...prevLgcDetailsMapped, ...values.lgc_details_mapped }; + // todo: 报价不能为空 + setLoading(true); + const success = await postProductsSaveAction({ travel_agency_id: activeAgency.travel_agency_id, info: readyToSubInfo, lgc_details: Object.values(mergedLgc), }); + setLoading(false); + success ? message.success(t('Success')) : message.error(t('Failed')); + // todo: 保存后更新数据 }; return ( <> diff --git a/src/views/products/Detail/ProductInfoForm.jsx b/src/views/products/Detail/ProductInfoForm.jsx index 4472b26..0d5fcb2 100644 --- a/src/views/products/Detail/ProductInfoForm.jsx +++ b/src/views/products/Detail/ProductInfoForm.jsx @@ -14,7 +14,7 @@ import { HT_HOST } from '@/config'; // import SearchInput from './SearchInput'; // import AuditStateSelector from './AuditStateSelector'; import { useProductsTypesMapVal, useProductsTypesFieldsets } from '@/hooks/useProductsSets'; -import useProductsStore from '@/stores/Products/Index'; +import useProductsStore, { postProductsSaveAction } from '@/stores/Products/Index'; import ProductInfoLgc from './ProductInfoLgc'; import ProductInfoQuotation from './ProductInfoQuotation'; import useAuthStore from '@/stores/Auth'; @@ -22,10 +22,10 @@ import { PERM_PRODUCTS_MANAGEMENT, PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFE const { RangePicker } = DatePicker; -const InfoForm = ({ onSubmit, onReset, onValuesChange, editable, showSubmit, confirmText, formName, loading, ...props }) => { +const InfoForm = ({ onSubmit, onReset, onValuesChange, editable, showSubmit, confirmText, formName, ...props }) => { const { t } = useTranslation('products'); const isPermitted = useAuthStore((state) => state.isPermitted); - const [agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.agencyProducts, state.editingProduct, state.setEditingProduct]); + const [loading, setLoading, agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.loading, state.setLoading, state.agencyProducts, state.editingProduct, state.setEditingProduct]); const weekdays = useWeekdays(); const [form] = Form.useForm(); const { sort, hides, fieldProps, fieldComProps } = { @@ -50,16 +50,15 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable, showSubmit, con }, [editingProduct?.info?.id]); const topPerm = isPermitted(PERM_PRODUCTS_OFFER_AUDIT); - const isNew = isEmpty(editingProduct?.info?.id); + const isNew = isEmpty(editingProduct?.info?.id) || editable; const ignoreEditable = topPerm || isNew; const onFinish = (values) => { console.log('Received values of form, origin form value: \n', values); const dest = formValuesMapper(values); console.log('form value send to onSubmit:\n', dest); - const str = new URLSearchParams(dest).toString(); if (typeof onSubmit === 'function') { - onSubmit(null, dest, values, str); + onSubmit(null, dest, values); } }; @@ -120,7 +119,8 @@ function getFields(props) { // console.log('getFields', props.initialValue); const styleProps = {}; const editableProps = (name) => { - const disabled = props.ignoreEditable ? false : (isEmpty(props.initialValue?.[name]) && props.editable ? false : true) + // const disabled = props.ignoreEditable ? false : (isEmpty(props.initialValue?.[name]) && props.editable ? false : true) + const disabled = !props.editable; return { disabled, className: disabled ? '!text-slate-500' : '' }; } const bigCol = 4 * 2; @@ -194,7 +194,7 @@ function getFields(props) { {/* */} handleChange('title', e.target.value)} // disabled={isCanEditable} - disabled={ignoreEditable ? false : (!isEmpty(ele.title) || !editable)} + // disabled={ignoreEditable ? false : (!isEmpty(ele.title) || !editable)} + disabled={!editable} /> handleChange('description', e.target.value)} - disabled={ignoreEditable ? false : (!isEmpty(ele.descriptions) || !editable)} + // disabled={ignoreEditable ? false : (!isEmpty(ele.descriptions) || !editable)} + disabled={!editable} />