diff --git a/src/hooks/useProductsSets.js b/src/hooks/useProductsSets.js index 710a39f..07c68ad 100644 --- a/src/hooks/useProductsSets.js +++ b/src/hooks/useProductsSets.js @@ -101,16 +101,17 @@ export const useProductsAuditStatesMapVal = (value) => { export const useProductsTypesFieldsets = (type) => { const [isPermitted] = useAuthStore((state) => [state.isPermitted]); const infoDefault = [['code'], ['title']]; - const infoAdmin = ['remarks', 'dept', ]; // 'display_to_c' + const infoAdmin = ['remarks', 'dept']; // 'display_to_c' + const infoDisplay = isPermitted(PERM_PRODUCTS_MANAGEMENT) ? ['display_to_c'] : []; const infoTypesMap = { - '6': [['city',],[]], + '6': [['city'], []], 'B': [['city', 'km'], []], - 'J': [['city', 'recommends_rate', 'duration', 'display_to_c'], ['description',]], - 'Q': [['city', 'recommends_rate', 'duration', 'display_to_c'], ['description',]], - 'D': [['city', 'recommends_rate','duration', 'display_to_c'], ['description',]], - '7': [['city', 'recommends_rate', 'duration', 'display_to_c', 'open_weekdays'], ['description',]], - 'R': [['city',], ['description',]], - '8': [['display_to_c'],[]], // todo: ? + 'J': [['city', 'recommends_rate', 'duration', ...infoDisplay], ['description']], + 'Q': [['city', 'recommends_rate', 'duration', ...infoDisplay], ['description']], + 'D': [['city', 'recommends_rate', 'duration', ...infoDisplay], ['description']], + '7': [['city', 'recommends_rate', 'duration', ...infoDisplay, 'open_weekdays'], ['description']], + 'R': [['city'], ['description']], + '8': [[...infoDisplay], []], }; const thisTypeFieldset = (_type) => { if (isEmpty(_type)) { @@ -119,8 +120,62 @@ export const useProductsTypesFieldsets = (type) => { const adminSet = isPermitted(PERM_PRODUCTS_MANAGEMENT) ? infoAdmin : []; return [ [...infoDefault[0], ...infoTypesMap[_type][0], ...adminSet], - [...infoDefault[1], ...infoTypesMap[_type][1]] + [...infoDefault[1], ...infoTypesMap[_type][1]], ]; }; return thisTypeFieldset(type); -} +}; + +export const useNewProductRecord = () => { + return { + info: { + 'id': null, + 'title': '', + 'code': '', + 'product_type_id': '', + 'product_type_name': '', + 'remarks': '', + 'duration': 0, + 'duration_unit': 'h', + 'open_weekdays': '', + 'recommends_rate': 0, + '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': '', + 'lastedit_changed': '', + }, + lgc_details: [ + { + 'title': '', + 'description': '', + 'lgc': 1, + 'id': null, + }, + ], + quotation: [], + }; +}; diff --git a/src/stores/Products/Index.js b/src/stores/Products/Index.js index 1a79d56..1b7c10b 100644 --- a/src/stores/Products/Index.js +++ b/src/stores/Products/Index.js @@ -107,6 +107,7 @@ const initialState = { activeAgency: {}, // 审核/编辑 页: 当前的供应商 agencyProducts: {}, // 审核/编辑 页: 供应商产品列表 editingProduct: {}, // 编辑页: 当前编辑的产品 + editing: false, }; export const useProductsStore = create( devtools((set, get) => ({ @@ -120,6 +121,7 @@ export const useProductsStore = create( setActiveAgency: (activeAgency) => set({ activeAgency }), setAgencyProducts: (agencyProducts) => set({ agencyProducts }), setEditingProduct: (editingProduct) => set({ editingProduct }), + setEditing: (editing) => set({ editing }), reset: () => set(initialState), diff --git a/src/views/products/Audit.jsx b/src/views/products/Audit.jsx index 8026a9c..371613d 100644 --- a/src/views/products/Audit.jsx +++ b/src/views/products/Audit.jsx @@ -135,7 +135,7 @@ const TypesPanels = (props) => { .map((w) => t(`weekdaysShort.${w}`)) .join(', '), info: c.info, - lgc_details: c.lgc_details.reduce((rlgc, clgc) => ({...r, [clgc.lgc]: clgc}), {}), + lgc_details: c.lgc_details.reduce((rlgc, clgc) => ({...rlgc, [clgc.lgc]: clgc}), {}), rowSpan: i === 0 ? c.quotation.length : 0, rowSpanI: [ri, i], })) diff --git a/src/views/products/Detail.jsx b/src/views/products/Detail.jsx index a1cdda6..49fd719 100644 --- a/src/views/products/Detail.jsx +++ b/src/views/products/Detail.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Tooltip, Button, Card, Col, Row, Breadcrumb, Table, Popconfirm, Form, Input, InputNumber, Tag, Modal, Select, Tree, FloatButton, DatePicker, Spin, message, Divider,Empty, Flex } from 'antd'; import { Link, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { useProductsTypes, useProductsAuditStatesMapVal, useProductsTypesMapVal } from '@/hooks/useProductsSets'; +import { useProductsTypes, useProductsAuditStatesMapVal, useProductsTypesMapVal, useNewProductRecord } from '@/hooks/useProductsSets'; import Extras from './Detail/Extras'; import { isEmpty } from '@/utils/commons'; import SecondHeaderWrapper from '@/components/SecondHeaderWrapper'; @@ -860,12 +860,20 @@ function Detail() { }; //新增产品 - const handelAddProduct = () => { + const newProduct = useNewProductRecord(); + // const { language } = useDefaultLgc(); + const handelAddProduct = () => { // 找到对应的产品类型节点 - const productTypeNode = treeData.find(item => item.key === addProductType); - console.log("productTypeNode", productTypeNode) - // if (productTypeNode) { - // // 在 children 数组中插入新的产品节点 + // const productTypeNode = treeData.find(item => item.key === addProductType); + const copyNewProduct = structuredClone(newProduct); + copyNewProduct.info.title = addproductName; + copyNewProduct.info.product_type_id = productsTypesMapVal[addProductType].value; + copyNewProduct.info.product_type_name = productsTypesMapVal[addProductType].label; + copyNewProduct.lgc_details[0].lgc = language; + setEditingProduct(copyNewProduct); + setAddProductVisible(false); + // todo: 树, active 类型节点 + return false; const tempAddData = { info: { id: "", @@ -1065,12 +1073,12 @@ function Detail() { // }> {isEmpty(agencyProducts) ? : -
+ <> {/* onNodeSelect={handleNodeSelect} */} -
+
{/* */} {/* */} @@ -1327,7 +1335,7 @@ function Detail() { ))} */} -
} + } ); } diff --git a/src/views/products/Detail/Header.jsx b/src/views/products/Detail/Header.jsx index 80e236b..ec0285f 100644 --- a/src/views/products/Detail/Header.jsx +++ b/src/views/products/Detail/Header.jsx @@ -23,7 +23,7 @@ const Header = ({ refresh, ...props }) => { const yearOptions = []; const currentYear = dayjs().year(); - const baseYear = Number(use_year === 'all' ? currentYear : use_year); + const baseYear = use_year ? Number(use_year === 'all' ? currentYear : use_year) : currentYear; for (let i = baseYear - 3; i <= baseYear + 3; i++) { yearOptions.push({ label: i, value: i }); } @@ -40,7 +40,7 @@ const Header = ({ refresh, ...props }) => { const emptyPickState = { value: '', label: t('products:State') }; useEffect(() => { - const baseState = audit_state === 'all' ? emptyPickState : stateMapVal[`${audit_state}`]; + const baseState = audit_state ? (audit_state === 'all' ? emptyPickState : stateMapVal[`${audit_state}`]) : emptyPickState; if (isEmpty(pickAuditState)) { setPickAuditState(baseState); } diff --git a/src/views/products/Detail/ProductInfo.jsx b/src/views/products/Detail/ProductInfo.jsx index 1de5dfe..b3f27c4 100644 --- a/src/views/products/Detail/ProductInfo.jsx +++ b/src/views/products/Detail/ProductInfo.jsx @@ -2,193 +2,44 @@ import { createContext, useEffect, useState } from 'react'; import { Breadcrumb, Form, Divider, Button, Input, Select, Row, Col } from 'antd'; import { useTranslation } from 'react-i18next'; import { useProductsTypesMapVal, } from '@/hooks/useProductsSets'; -import useProductsStore from '@/stores/Products/Index'; +import useProductsStore, { postProductsSave } 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 DeptSelector from '@/components/DeptSelector'; import CitySelector from '@/components/CitySelector'; -import { at, isEmpty } from '@/utils/commons'; +import { at, isEmpty, pick } from '@/utils/commons'; import ProductInfoForm from './ProductInfoForm'; const ProductInfo = ({ ...props }) => { const { t } = useTranslation(); - const [form] = Form.useForm(); + const isPermitted = useAuthStore((state) => state.isPermitted); const productsTypesMapVal = useProductsTypesMapVal(); - const [agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.agencyProducts, state.editingProduct, state.setEditingProduct]); + const [activeAgency, agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.activeAgency, state.agencyProducts, state.editingProduct, state.setEditingProduct]); + const [editable, setEditable] = useState(true); useEffect(() => { + const notAudit = activeAgency.audit_state_id < 0 || activeAgency.audit_state_id === 3; + const hasAuditPer = isPermitted(PERM_PRODUCTS_OFFER_AUDIT); + const hasEditPer = isPermitted(PERM_PRODUCTS_OFFER_PUT); + setEditable(notAudit && hasEditPer); + // setEditable(true); // test: 0 + return () => {}; + }, [activeAgency, editingProduct]) - return () => { - - } - }, [editingProduct]) - - - const productTypeFormItems = { - '6': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - ], - 'B': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - { key: 'km', name: t('products:KM'), nameKey: 'products:KM' }, - { - key: 'remarks', - name: {t('products:Remarks')}, - nameKey: 'products:Remarks', - }, - ], - 'J': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - { - key: 'recommends_rate', - name: {t('products:recommendationRate')}, - nameKey: 'products:recommendationRate', - }, - { key: 'duration', name: t('products:Duration'), nameKey: 'products:Duration' }, - { - key: 'dept_name', - name: {t('products:Dept')}, - nameKey: 'products:Dept', - }, - { - key: 'display_to_c', - name: {t('products:DisplayToC')}, - nameKey: 'products:DisplayToC', - }, - { - key: 'remarks', - name: {t('products:Remarks')}, - nameKey: 'products:Remarks', - }, - ], - 'Q': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - { - key: 'recommends_rate', - name: {t('products:recommendationRate')}, - nameKey: 'products:recommendationRate', - }, - { key: 'duration', name: t('products:Duration'), nameKey: 'products:Duration' }, - { - key: 'dept_name', - name: {t('products:Dept')}, - nameKey: 'products:Dept', - }, - { - key: 'display_to_c', - name: {t('products:DisplayToC')}, - nameKey: 'products:DisplayToC', - }, - { - key: 'remarks', - name: {t('products:Remarks')}, - nameKey: 'products:Remarks', - }, - ], - 'D': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - { - key: 'recommends_rate', - name: {t('products:recommendationRate')}, - nameKey: 'products:recommendationRate', - }, - { key: 'duration', name: t('products:Duration'), nameKey: 'products:Duration' }, - { - key: 'dept_name', - name: {t('products:Dept')}, - nameKey: 'products:Dept', - }, - { - key: 'display_to_c', - name: {t('products:DisplayToC')}, - nameKey: 'products:DisplayToC', - }, - { - key: 'remarks', - name: {t('products:Remarks')}, - nameKey: 'products:Remarks', - }, - ], - '7': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - { - key: 'recommends_rate', - name: {t('products:recommendationRate')}, - nameKey: 'products:recommendationRate', - }, - { key: 'duration', name: t('products:Duration'), nameKey: 'products:Duration' }, - { key: 'open_weekdays', name: t('products:OpenWeekdays'), nameKey: 'products:OpenWeekdays' }, - { - key: 'remarks', - name: {t('products:Remarks')}, - nameKey: 'products:Remarks', - }, - ], - '8': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - ], - 'R': [ - { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }, - { key: 'city_name', name: t('products:City'), nameKey: 'products:City' }, - ], - }; - const isCanEditable = false; - const renderFormItem = (item) => { - // const item = { key: 'code', name: t('products:Code'), nameKey: 'products:Code' }; - // console.log(editingProduct?.info); - if (isEmpty(editingProduct)) { - return null; - } - console.log(item.key, at(editingProduct?.info, item.key)[0]); - let InputCom = ; - switch (item.key) { - case 'duration': - InputCom = ; - break; - case 'display_to_c': - InputCom = ( - - ); - break; - case 'dept_name': - InputCom = ; - break; - case 'city_name': - InputCom = ; - break; - case 'remarks': - InputCom = ; - break; - default: - InputCom = ; - } - return ( - - - {/* {renderFormItem(item)} */} - - - - ); - }; - - const onValuesChange = (changedValues, allValues) => { - // const dest = formValuesMapper(allValues); - console.log('form onValuesChange', Object.keys(changedValues), ); - }; - const onSave = (e) => { - console.log(e); + const onSave = (err, values, forms) => { + values.travel_agency_id = activeAgency.travel_agency_id; + const poster = { + "audit_state": "-1", + // "create_date": "", + // "created_by": "", + "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); }; return ( <> @@ -200,16 +51,7 @@ const ProductInfo = ({ ...props }) => { />

{t('products:EditComponents.info')}

- - {/*
- -
- -
-
-
*/} + ); diff --git a/src/views/products/Detail/ProductInfoForm.jsx b/src/views/products/Detail/ProductInfoForm.jsx index c53afe4..ccb96e5 100644 --- a/src/views/products/Detail/ProductInfoForm.jsx +++ b/src/views/products/Detail/ProductInfoForm.jsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { Form, Input, Row, Col, Select, DatePicker, Space, Button, InputNumber, Radio, Checkbox, Divider } from 'antd'; -import { objectMapper, at } from '@/utils/commons'; +import { objectMapper, at, isEmpty } from '@/utils/commons'; import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from '@/config'; // import useFormStore from '@/stores/Form'; import { useTranslation } from 'react-i18next'; @@ -74,8 +74,8 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s return ( <>
- - {getFields({ sort, initialValue: editingProduct?.info, hides, shows, fieldProps, fieldComProps, form, t, dataSets: { weekdays } })} + + {getFields({ sort, initialValue: editingProduct?.info, hides, shows, fieldProps, fieldComProps, form, t, dataSets: { weekdays }, editable })} {/* {showSubmit && ( @@ -88,13 +88,13 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s {/* */} - - + + - {showSubmit && ( + {editable && (