diff --git a/public/locales/en/products.json b/public/locales/en/products.json
index 50bda51..79ca29e 100644
--- a/public/locales/en/products.json
+++ b/public/locales/en/products.json
@@ -115,5 +115,5 @@
"Weekdays": "Weekdays"
},
- "#": "Products"
+ "#": "Product"
}
diff --git a/src/views/products/Detail.jsx b/src/views/products/Detail.jsx
index 95eb087..87d8a1b 100644
--- a/src/views/products/Detail.jsx
+++ b/src/views/products/Detail.jsx
@@ -1,5 +1,28 @@
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 {
+ 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, useNewProductRecord } from '@/hooks/useProductsSets';
@@ -7,10 +30,9 @@ import Extras from './Detail/Extras';
import { isEmpty } from '@/utils/commons';
import SecondHeaderWrapper from '@/components/SecondHeaderWrapper';
import Header from './Detail/Header';
-import YearSelector from './Detail/YearSelector'
+import YearSelector from './Detail/YearSelector';
import { useParams } from 'react-router-dom';
import useProductsStore from '@/stores/Products/Index';
-import postProductsSave from '@/stores/Products/Index';
import { useHTLanguageSets } from '@/hooks/useHTLanguageSets';
import { useDefaultLgc } from '@/i18n/LanguageSwitcher';
import BatchImportPrice from './Detail/BatchImportPrice';
@@ -21,1031 +43,180 @@ import { useDatePresets } from '@/hooks/useDatePresets';
import CitySelector from '@/components/CitySelector';
import { HT_HOST } from '@/config';
import { postJSON, postForm } from '@/utils/request';
-import RequireAuth from '@/components/RequireAuth'
-import { PERM_ROLE_NEW } from '@/config'
+import RequireAuth from '@/components/RequireAuth';
+import { PERM_ROLE_NEW } from '@/config';
import { create } from 'zustand';
import { PERM_PRODUCTS_MANAGEMENT, PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFER_PUT } from '@/config';
import { usingStorage } from '@/hooks/usingStorage';
import ProductsTree from './Detail/ProductsTree';
import ProductInfo from './Detail/ProductInfo';
import useAuthStore from '@/stores/Auth';
+import NewProductModal from './Detail/NewProductModal';
function Detail() {
- const { t } = useTranslation();
- const productsTypesMapVal = useProductsTypesMapVal();
- const [form] = Form.useForm();
- const navigate = useNavigate()
- const { RangePicker } = DatePicker;
- const [tags, setTags] = useState([]);
- const [isModalVisible, setIsModalVisible] = useState(false);
- const [selectedTag, setSelectedTag] = useState(null);
- const [batchImportPriceVisible, setBatchImportPriceVisible] = useState(false);
- const [quotationTableVisible, setQuotationTableVisible] = useState(false)
- const [languageStatus, setLanguageStatus] = useState(null);
- const [selectedNodeid, setSelectedNodeid] = useState(null);
- const [remainderLanguage, setRemainderLanguage] = useState([])
- const [treeData, setTreeData] = useState([]);
- const productsTypes = useProductsTypes();
- const [productsData, setProductsData] = useState(null);
+ // const { t } = useTranslation();
+ const navigate = useNavigate();
const [quotation, setQuotation] = useState(null);
const [lgc_details, setLgc_details] = useState(null);
- const [languageLabel, setLanguageLabel] = useState(null);
+ // const [languageLabel, setLanguageLabel] = useState(null);
const { travel_agency_id, audit_state, use_year } = useParams();
- const { language } = useDefaultLgc();
- const HTLanguageSets = useHTLanguageSets();
- const { Search } = Input;
+ // const HTLanguageSets = useHTLanguageSets();
+ // const { Search } = Input;
const [addProductVisible, setAddProductVisible] = useState(false);
const [editingProduct, setEditingProduct] = useProductsStore((state) => [state.editingProduct, state.setEditingProduct]);
- const [agencyProducts, setAgencyProducts,loading] = useProductsStore((state) => [state.agencyProducts, state.setAgencyProducts, state.loading]);
+ const [agencyProducts, setAgencyProducts, loading] = useProductsStore((state) => [state.agencyProducts, state.setAgencyProducts, state.loading]);
const { getAgencyProducts, activeAgency } = useProductsStore();
- const [expandedKeys, setExpandedKeys] = useState([]);
- const [searchValue, setSearchValue] = useState('');
- const [autoExpandParent, setAutoExpandParent] = useState(true);
- const [dataList, setDataList] = useState([]);
- const [defaultData, setDefaultData] = useState([]);
- const [batchImportData, setBatchImportData] = useState([]);
- const [addProductType, setAddProductType] = useState('');
- const [addproductName, setAddProductName] = useState('');
- const [dataFetched, setDataFetched] = useState(false); // 添加一个标志位
- const [selectedDays, setSelectedDays] = useState([]);
- const [weekdays, setWeekdays] = useState([]);
const [info, setInfo] = useState();
const yearOptions = [];
const currentYear = dayjs().year();
const baseYear = Number(use_year === 'all' ? currentYear : use_year);
for (let i = baseYear - 3; i <= baseYear + 3; i++) {
- yearOptions.push({ label: i, value: i, });
+ yearOptions.push({ label: i, value: i });
}
- const [param, setParam] = useState({ pick_year: baseYear, pick_agency: travel_agency_id });
- const [pickYear, setPickYear] = useState(baseYear);
- const handleYearChange = (value) => {
- setPickYear(value);
- setParam((pre) => ({ ...pre, ...{ pick_year: value } }));
- };
const { travelAgencyId } = usingStorage();
- const handleGetAgencyProducts = ({pick_year, pick_agency, pick_state}={}) => {
+ const handleGetAgencyProducts = ({ pick_year, pick_agency, pick_state } = {}) => {
const year = pick_year || use_year || dayjs().year();
const agency = pick_agency || travel_agency_id || travelAgencyId;
const state = pick_state ?? audit_state;
- console.log("loading",loading);
getAgencyProducts({ travel_agency_id: agency, use_year: year, audit_state: state });
- console.log("loading",loading);
- console.log("AgencyProducts",agencyProducts);
+ // console.log("AgencyProducts",agencyProducts);
// navigate(`/products/${agency}/${year}/${audit_state}/edit`);
-
- };
- const travel_agency_name = activeAgency.travel_agency_name;
- const audit_state_id = activeAgency.audit_state_id;
- let isCanEditable = !(audit_state_id === 1 || audit_state_id === 3 || audit_state_id === -1)
- const [currentQuotationRecord, setCurrentQuotationRecord] = useState({
- use_dates_start: null,
- use_dates_end: null
- });
- const formatDate = (date) => (date ? dayjs(date) : null);
- const stateMapVal = useProductsAuditStatesMapVal();
-
- const startDate = currentQuotationRecord.use_dates_start && dayjs(currentQuotationRecord.use_dates_start).isValid()
- ? formatDate(currentQuotationRecord.use_dates_start)
- : null;
- const endDate = currentQuotationRecord.use_dates_end && dayjs(currentQuotationRecord.use_dates_end).isValid()
- ? formatDate(currentQuotationRecord.use_dates_end)
- : null;
-
-
- const [editIndex, setEditIndex] = useState(null);
- const presets = useDatePresets();
- const handleBatchImportData = (data) => {
- setBatchImportData(data);
};
- const days = [
- 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'
- ];
- const productProject = {
- "6": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- ],
- "B": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- { code: "km", name: t('products:KM'), nameKey: 'products:KM' },
- {
- code: "remarks",
- name: (
-
- {t('products:Remarks')}
-
- ),
- nameKey: 'products:Remarks',
- },
- ],
- "J": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- {
- code: "recommends_rate",
- name: (
-
- {t('products:recommendationRate')}
-
- ),
- nameKey: 'products:recommendationRate',
- },
- { code: "duration", name: t('products:Duration'), nameKey: 'products:Duration' },
- {
- code: "dept_name",
- name: (
-
- {t('products:Dept')}
-
- ),
- nameKey: 'products:Dept',
- },
- {
- code: "display_to_c",
- name: (
-
- {t('products:DisplayToC')}
-
- ),
- nameKey: 'products:DisplayToC',
- },
- {
- code: "remarks",
- name: (
-
- {t('products:Remarks')}
-
- ),
- nameKey: 'products:Remarks',
- },
- ],
- "Q": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- {
- code: "recommends_rate",
- name: (
-
- {t('products:recommendationRate')}
-
- ),
- nameKey: 'products:recommendationRate',
- },
- { code: "duration", name: t('products:Duration'), nameKey: 'products:Duration' },
- {
- code: "dept_name",
- name: (
-
- {t('products:Dept')}
-
- ),
- nameKey: 'products:Dept',
- },
- {
- code: "display_to_c",
- name: (
-
- {t('products:DisplayToC')}
-
- ),
- nameKey: 'products:DisplayToC',
- },
- {
- code: "remarks",
- name: (
-
- {t('products:Remarks')}
-
- ),
- nameKey: 'products:Remarks',
- },
- ],
- "D": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- {
- code: "recommends_rate",
- name: (
-
- {t('products:recommendationRate')}
-
- ),
- nameKey: 'products:recommendationRate',
- },
- { code: "duration", name: t('products:Duration'), nameKey: 'products:Duration' },
- {
- code: "dept_name",
- name: (
-
- {t('products:Dept')}
-
- ),
- nameKey: 'products:Dept',
- },
- {
- code: "display_to_c",
- name: (
-
- {t('products:DisplayToC')}
-
- ),
- nameKey: 'products:DisplayToC',
- },
- {
- code: "remarks",
- name: (
-
- {t('products:Remarks')}
-
- ),
- nameKey: 'products:Remarks',
- },
- ],
- "7": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- {
- code: "recommends_rate",
- name: (
-
- {t('products:recommendationRate')}
-
- ),
- nameKey: 'products:recommendationRate',
- },
- { code: "duration", name: t('products:Duration'), nameKey: 'products:Duration' },
- { code: "open_weekdays", name: t('products:OpenWeekdays'), nameKey: 'products:OpenWeekdays' },
- {
- code: "remarks",
- name: (
-
- {t('products:Remarks')}
-
- ),
- nameKey: 'products:Remarks',
- },
- ],
- "8": [
- { code: "code", name: t('products:Code') },
- { code: "city_name", name: t('products:City') },
- ],
- "R": [
- { code: "code", name: t('products:Code'), nameKey: 'products:Code' },
- { code: "city_name", name: t('products:City'), nameKey: 'products:City' },
- ]
- }
- const [selectedCategory, setSelectedCategory] = useState([]);
-
- useEffect(() => {
- setLanguageStatus(language);
- const matchedLanguage = HTLanguageSets.find(HTLanguage => HTLanguage.key === language.toString());
- const languageLabel = matchedLanguage.label
- setLanguageLabel(languageLabel)
- setSelectedTag(languageLabel)
- // setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString()))
-
- }, []);
- useEffect(()=>{
- handleGetAgencyProducts(param);
- },[param]);
-
-
-
- useEffect(() => {
- editingProductQuotation();
- }, [treeData, editingProduct])
-
- const editingProductQuotation = () => {
- console.log("editingProduct", editingProduct)
- const editingProductID = editingProduct.id;
- console.log("editingProductID", editingProductID)
- let stopProgram = false;
- for (const element of treeData) {
- if (stopProgram) {
- return;
- }
- const childList = element.children;
- for (const product of childList) {
- const childrenID = product.key.split('-')[1];
- if (editingProductID == childrenID) {
- const fatherKey = product.key.split('-')[0];
- setSelectedCategory(productProject[fatherKey]);
- stopProgram = true;
- const tempInfo = product._raw.info;
- const tempLgc_details = product._raw.lgc_details.find(record => record.lgc === 2);
- console.log("tempLgc_details", tempLgc_details);
- const tempQuotation = product._raw.quotation;
- console.log({
- info: tempInfo,
- lgc_details: {
- title: tempLgc_details.title,
- description: tempLgc_details.descriptions
- },
- })
- setQuotation(tempQuotation);
- setTags([languageLabel]);
- setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString()));
-
- form.setFieldsValue({
- info: tempInfo,
- lgc_details: {
- title: tempLgc_details.title,
- description: tempLgc_details.descriptions
- },
- })
- break;
- }
- }
-
- }
- }
// useEffect(() => {
- // const fetchData = async () => {
- // if (productsTypes.length > 0 && travel_agency_id && Object.keys(agencyProducts).length > 0) {
- // const generateTreeData = (productsTypes, productsData) => {
- // return productsTypes.map(type => ({
- // title: type.label,
- // key: type.value,
- // selectable: false,
- // children: (productsData[type.value] || []).map(product => ({
- // title: product.info.title,
- // key: `${type.value}-${product.info.id}`,
- // _raw: product,
- // })),
- // }));
- // };
- // const tempExpandedKeys = productsTypes.map(item => item.key);
- // const treeData = generateTreeData(productsTypes, agencyProducts);
- // setTreeData(treeData);
- // setExpandedKeys(tempExpandedKeys);
- // setProductsData(agencyProducts);
- // setDefaultData(treeData);
- // setDataList(flattenTreeData(treeData));
- // setDataFetched(true);
+ // editingProductQuotation();
+ // }, [treeData, editingProduct]);
+
+ // const editingProductQuotation = () => {
+ // console.log('editingProduct', editingProduct);
+ // const editingProductID = editingProduct.id;
+ // console.log('editingProductID', editingProductID);
+ // let stopProgram = false;
+ // for (const element of treeData) {
+ // if (stopProgram) {
+ // return;
// }
- // };
- // fetchData();
- // }, [productsTypes, travel_agency_id, use_year, audit_state, agencyProducts]);
-
- // const flattenTreeData = (tree) => {
- // let flatList = [];
- // const flatten = (nodes) => {
- // nodes.forEach((node) => {
- // flatList.push({ title: node.title, key: node.key });
- // if (node.children) {
- // flatten(node.children);
- // }
- // });
- // };
- // flatten(tree);
- // return flatList;
- // };
-
- // const getParentKey = (key, tree) => {
- // let parentKey;
- // for (let i = 0; i < tree.length; i++) {
- // const node = tree[i];
- // if (node.children) {
- // if (node.children.some((item) => item.key === key)) {
- // parentKey = node.key;
- // } else {
- // const pKey = getParentKey(key, node.children);
- // if (pKey) {
- // parentKey = pKey;
- // }
+ // const childList = element.children;
+ // for (const product of childList) {
+ // const childrenID = product.key.split('-')[1];
+ // if (editingProductID == childrenID) {
+ // const fatherKey = product.key.split('-')[0];
+ // setSelectedCategory(productProject[fatherKey]);
+ // stopProgram = true;
+ // const tempInfo = product._raw.info;
+ // const tempLgc_details = product._raw.lgc_details.find((record) => record.lgc === 2);
+ // console.log('tempLgc_details', tempLgc_details);
+ // const tempQuotation = product._raw.quotation;
+ // console.log({
+ // info: tempInfo,
+ // lgc_details: {
+ // title: tempLgc_details.title,
+ // description: tempLgc_details.descriptions,
+ // },
+ // });
+ // setQuotation(tempQuotation);
+ // setTags([languageLabel]);
+ // setRemainderLanguage(HTLanguageSets.filter((item) => item.key !== language.toString()));
+
+ // form.setFieldsValue({
+ // info: tempInfo,
+ // lgc_details: {
+ // title: tempLgc_details.title,
+ // description: tempLgc_details.descriptions,
+ // },
+ // });
+ // break;
// }
// }
// }
- // return parentKey;
- // };
-
- // const titleRender = (node) => {
- // const index = node.title.indexOf(searchValue);
- // const beforeStr = node.title.substr(0, index);
- // const afterStr = node.title.substr(index + searchValue.length);
- // const highlighted = (
- // {searchValue}
- // );
-
- // return index > -1 ? (
- //
- // {beforeStr}
- // {highlighted}
- // {afterStr}
- //
- // ) : (
- // {node.title}
- // );
- // };
-
-
- // const onChange = (e) => {
- // const { value } = e.target;
- // const newExpandedKeys = dataList
- // .filter(item => item.title.includes(value))
- // .map(item => getParentKey(item.key, defaultData))
- // .filter((item, i, self) => item && self.indexOf(item) === i);
- // setExpandedKeys(newExpandedKeys);
- // setSearchValue(value);
- // setAutoExpandParent(true);
- // };
-
- // const onExpand = (keys) => {
- // setExpandedKeys(keys);
- // setAutoExpandParent(false);
// };
- const edit = (record, index) => {
- setQuotationTableVisible(true);
- setEditIndex(index);
- setCurrentQuotationRecord(record);
- };
-
-
- const handleDelete = (index) => {
- const newData = [...quotation];
- newData.splice(index, 1);
- const sortedData = [...newData].sort((a, b) => {
- const aValidPeriod = dayjs(a.use_dates_end).diff(dayjs(a.use_dates_start));
- const bValidPeriod = dayjs(b.use_dates_end).diff(dayjs(b.use_dates_start));
- if (aValidPeriod !== bValidPeriod) {
- return aValidPeriod - bValidPeriod;
- }
- const aGroupSize = a.group_size_max - a.group_size_min;
- const bGroupSize = b.group_size_max - b.group_size_min;
-
- return aGroupSize - bGroupSize;
- });
- setQuotation(sortedData);
- };
-
- const handleAdd = () => {
- const newData = {
- adult_cost: 0,
- child_cost: 0,
- currency: '',
- group_size_min: 0,
- group_size_max: 0,
- id: '',
- lastedit_changed: '',
- use_dates_start: '',
- use_dates_end: '',
- weekdays: '',
- tempKey: Math.random()
- };
- setQuotation([...quotation, newData]);
- const index = [...quotation, newData].length - 1
- edit(newData, index);
- };
-
- const handleBatchImport = () => {
- setBatchImportPriceVisible(true);
- }
-
- const quotationTableVisibleOK = () => {
- currentQuotationRecord.use_dates_start = dayjs(currentQuotationRecord.use_dates_start).format('YYYY-MM-DD')
- currentQuotationRecord.use_dates_end = dayjs(currentQuotationRecord.use_dates_end).format('YYYY-MM-DD')
- const tempQuotation = [...quotation];
- tempQuotation[editIndex] = { ...currentQuotationRecord, weekdays: weekdays };
- const sortedData = [...tempQuotation].sort((a, b) => {
- const aValidPeriod = dayjs(a.use_dates_end).diff(dayjs(a.use_dates_start));
- const bValidPeriod = dayjs(b.use_dates_end).diff(dayjs(b.use_dates_start));
-
- if (aValidPeriod !== bValidPeriod) {
- return aValidPeriod - bValidPeriod;
- }
- const aGroupSize = a.group_size_max - a.group_size_min;
- const bGroupSize = b.group_size_max - b.group_size_min;
-
- return aGroupSize - bGroupSize;
- });
- setQuotation(sortedData);
- setQuotationTableVisible(false);
- }
- const quotationTableVisibleCancel = () => {
- setQuotationTableVisible(false);
- }
-
-
- const handleBatchImportOK = () => {
- const tempBatchImportData = batchImportData.map(item => {
- const { tag, validPeriod, ...rest } = item;
- return rest;
- });
- const newData = [...quotation, ...tempBatchImportData];
- const sortedData = [...newData].sort((a, b) => {
- if (a.group_size_min !== b.group_size_min) {
- return a.group_size_min - b.group_size_min;
- }
-
- return a.group_size_max - b.group_size_max;
- });
-
-
- setQuotation(sortedData);
- setBatchImportPriceVisible(false);
- }
-
-
-
- const columns = [
- { title: t('products:adultPrice'), dataIndex: 'adult_cost', width: '10%', editable: true },
- { title: t('products:childrenPrice'), dataIndex: 'child_cost', width: '10%', editable: true },
- { title: t('products:currency'), dataIndex: 'currency', width: '10%', editable: true },
- {
- title: t('products:Types'),
- dataIndex: 'unit',
- width: '10%',
- editable: true,
- render: (text) => (text === '0' ? '每人' : text === '1' ? '每团' : text),
- },
- {
- title: t('products:number'),
- dataIndex: 'group_size',
- width: '20%',
- editable: true,
- render: (_, record) => `${record.group_size_min}-${record.group_size_max}`
- },
-
- {
- title: t('products:validityPeriod'),
- dataIndex: 'validityPeriod',
- width: '20%',
- editable: true,
- render: (_, record) => `${record.use_dates_start}-${record.use_dates_end}`
- },
-
- { title: t('products:Weekdays'), dataIndex: 'weekdays', width: '10%' },
-
- ];
-
- // 根据条件判断是否要添加操作列
- if (!isCanEditable) {
- columns.push({
- title: t('products:operation'),
- dataIndex: 'operation',
- render: (_, record, index) => {
- const canEdit = record.audit_state_id === -1;
- return (
-
- {canEdit ? (
- edit(record, index)} style={{ marginRight: 8 }}>{t('Edit')}
- ) : (
- {t('Edit')}
- )}
- {canEdit ? (
- handleDelete(index)}>
- {t('Delete')}
-
- ) : (
- {t('Delete')}
- )}
-
- );
- }
- });
- }
-
- const handleTagClick = (tag) => {
- setSelectedTag(tag);
- const matchedLanguage = HTLanguageSets.find(language => language.label === tag);
- const key = matchedLanguage ? matchedLanguage.key : null;
- form.setFieldsValue({
- lgc_details: {
- title: lgc_details[key] ? lgc_details[key].title : '',
- description: lgc_details[key] ? lgc_details[key].description : ''
- }
- });
- setLanguageStatus(key)
-
- };
-
- const showModal = () => setIsModalVisible(true);
-
- const handleOk = () => {
- if (!selectedTag) return;
- if (!remainderLanguage.some(item => item.label === selectedTag)) return;
- if (remainderLanguage.includes(selectedTag)) return;
- let tempRemainderLanguage = remainderLanguage.filter((item) => {
- return item.label !== selectedTag;
- })
-
-
- const matchedLanguage = HTLanguageSets.find(HTLanguage => HTLanguage.label === selectedTag);
- const languageKey = parseInt(matchedLanguage.key)
- if (!(languageKey in lgc_details)) {
- const tempLgc_details = {
- ...lgc_details, [languageKey]: {
- title: "",
- lgc: languageKey,
- description: "",
- id: ""
- }
- }
- setLgc_details(tempLgc_details)
- }
-
- setRemainderLanguage(tempRemainderLanguage)
- setTags([...tags, selectedTag])
-
- setSelectedTag(null);
- setIsModalVisible(false);
- }
-
- const handleCancel = () => setIsModalVisible(false);
-
-
- const handleTagChange = (value) => {
- setSelectedTag(value);
- };
-
- const handleChange = (field, value) => {
- // 更新整个 lgc_details 对象
- const updatedLgcDetails = {
- ...lgc_details,
- [languageStatus]: {
- ...lgc_details[languageStatus],
- [field]: value,
- lgc: languageStatus.toString(),
- id: lgc_details[languageStatus]?.id || ''
- }
- };
- setLgc_details(updatedLgcDetails)
-
- };
-
- const handleDayClick = (dayIndex) => {
- const dayOfWeek = (dayIndex % 7) + 1;
-
- setSelectedDays((prevSelectedDays) => {
- const updatedDays = prevSelectedDays.includes(dayOfWeek)
- ? prevSelectedDays.filter((d) => d !== dayOfWeek)
- : [...prevSelectedDays, dayOfWeek];
- const weekdaysString = updatedDays.sort().join(',');
- setWeekdays(weekdaysString);
- return updatedDays;
- });
- };
-
- //树组件方法
- const handleNodeSelect = (_, { node }) => {
- setSelectedNodeid(node.key);
- // const fatherKey = node.key.split('-')[0];
- const fatherKey = node._raw.info.product_type_id;
- setSelectedCategory(productProject[fatherKey]);
- setTags([languageLabel]);
- // 如果点击的是同一个节点,不做任何操作
- if (selectedNodeid === node.key) return;
- setLanguageStatus(language);
- const matchedLanguage = HTLanguageSets.find(HTLanguage => HTLanguage.key === language.toString());
- const languageLabelRefresh = matchedLanguage.label;
- setLanguageLabel(languageLabelRefresh);
- setSelectedTag(languageLabelRefresh);
- setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString()));
- // setEditingProduct(node._raw);
- if (!node._raw.info.id) {
- let infoData = node._raw.info;
- setInfo(node._raw.info);
- const newLgcDetails = node._raw.lgc_details
- setSelectedNodeid(node.key);
- form.setFieldsValue({
- info: {
- id: infoData.id || "",
- title: infoData.title || "",
- code: infoData.code || "",
- type: infoData.product_type_id || "",
- audit_state: "-1",
- create_date: infoData.create_date || "",
- created_by: infoData.created_by || "",
- travel_agency_id: travel_agency_id || "",
- travel_agency_name: activeAgency.travel_agency_name || "",
- lastedit_changed: infoData.lastedit_changed || "",
- remarks: infoData.remarks || "",
- duration: infoData.duration || "",
- duration_unit: infoData.duration_unit || "",
- open_weekdays: infoData.open_weekdays || "",
- recommends_rate: infoData.recommends_rate || "",
- dept: infoData.dept_id || "",
- display_to_c: infoData.display_to_c || "",
- km: infoData.km || "",
- city_name: infoData.city_name || "",
- city_id: infoData.city_id || "",
- // product_type_name: infoData.product_type_name || "",
- // dept_name: infoData.dept_name || "",
-
- },
- lgc_details: {
- lgc: language,
- title: newLgcDetails[language]?.title || '',
- description: newLgcDetails[language]?.description || ''
- }
- })
- setLgc_details([])
- setQuotation([{
- adult_cost: 0,
- child_cost: 0,
- currency: '',
- group_size_min: 0,
- group_size_max: 0,
- id: '',
- lastedit_changed: '',
- use_dates_start: '',
- use_dates_end: '',
- weekdays: '',
- tempKey: Math.random()
- }])
- return
- } else {
- let initialQuotationData = null;
- let infoData = null;
- let lgcDetailsData = null;
- console.log("")
- // productsData[fatherKey].forEach(element => {
- // if (element.info.id === node._raw.info.id) {
- // initialQuotationData = element.quotation;
- // infoData = element.info;
- // lgcDetailsData = element.lgc_details.map(item => {
- // const newItem = {
- // ...item,
- // description: item.descriptions,
- // };
- // delete newItem.descriptions;
- // return newItem;
- // });
- // }
- // });
- // const quotationData = initialQuotationData.map(element => {
- // const updatedObject = {
- // ...element,
- // unit: element.unit_id,
- // tempKey: Math.random()
- // };
- // delete updatedObject.unit_name;
- // delete updatedObject.unit_id;
- // // delete updatedObject.audit_state_id;
- // delete updatedObject.audit_state_name;
- // return updatedObject;
- // });
-
-
- // if (!node._raw.info.id) {
-
- // }
- // // 累积 lgc_details 数据
- // let newLgcDetails = {};
- // if (lgcDetailsData) {
- // lgcDetailsData.forEach(element => {
- // newLgcDetails[element.lgc] = element;
- // });
- // }
-
- // setLgc_details(newLgcDetails);
-
-
- // let sortedData = [...quotationData].sort((a, b) => {
- // // 计算有效期范围大小
- // const aValidPeriod = dayjs(a.use_dates_end).diff(dayjs(a.use_dates_start));
- // const bValidPeriod = dayjs(b.use_dates_end).diff(dayjs(b.use_dates_start));
-
- // // 按照有效期范围大小升序排序
- // if (aValidPeriod !== bValidPeriod) {
- // return aValidPeriod - bValidPeriod;
- // }
-
- // // 如果有效期范围相同,则按照人数范围大小升序排序
- // const aGroupSize = a.group_size_max - a.group_size_min;
- // const bGroupSize = b.group_size_max - b.group_size_min;
-
- // return aGroupSize - bGroupSize;
- // });
-
- // const tempInfo = {
- // id: infoData.id || "",
- // title: infoData.title || "",
- // code: infoData.code || "",
- // type: infoData.product_type_id || "",
- // create_date: infoData.create_date || "",
- // created_by: infoData.created_by || "",
- // travel_agency_id: travel_agency_id || "",
- // travel_agency_name: activeAgency.travel_agency_name || "",
- // lastedit_changed: infoData.lastedit_changed || "",
- // remarks: infoData.remarks || "",
- // duration: infoData.duration || "",
- // duration_unit: infoData.duration_unit || "",
- // open_weekdays: infoData.open_weekdays || "",
- // recommends_rate: infoData.recommends_rate || "",
- // dept: infoData.dept_id || "",
- // display_to_c: infoData.display_to_c || "",
- // km: infoData.km || "",
- // city_name: infoData.city_name || "",
- // city_id: infoData.city_id || "",
- // product_type_name: infoData.product_type_name || "",
- // dept_name: infoData.dept_name || "",
- // };
- // setInfo(tempInfo);
- // setQuotation(sortedData);
- // if (node._raw.info.id) {
- // form.setFieldsValue({
- // info: tempInfo,
- // lgc_details: {
- // lgc: language,
- // title: newLgcDetails[language]?.title || '',
- // description: newLgcDetails[language]?.description || ''
- // }
- // });
- // }
- }
-
- };
-
-const isPermitted = useAuthStore((state) => state.isPermitted);
-const [editable, setEditable] = useState(true);
+ const isPermitted = useAuthStore((state) => state.isPermitted);
+ 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(hasAuditPer ? true : (notAudit && hasEditPer));
+ setEditable(hasAuditPer ? true : notAudit && hasEditPer);
// setEditable(true); // debug: 0
// console.log('editable', hasAuditPer, (notAudit && hasEditPer));
return () => {};
- }, [activeAgency, editingProduct])
-
- //新增产品
- const newProduct = useNewProductRecord();
- // const { language } = useDefaultLgc();
- const handelAddProduct = () => {
- // 找到对应的产品类型节点
- // 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);
- return false;
- const tempAddData = {
- info: {
- id: "",
- title: addproductName,
- code: "",
- type: addProductType,
- create_date: "",
- created_by: "",
- travel_agency_id: "",
- travel_agency_name: "",
- lastedit_changed: "",
- remarks: "",
- duration: "",
- duration_unit: "",
- open_weekdays: "",
- recommends_rate: "",
- dept: "",
- display_to_c: "",
- km: "",
- city_name: "",
- city_id: "",
- product_type_name: "",
- dept_name: "",
- },
- lgc_details: [
- ],
- quotation: []
- }
- const newChildren = [
- ...productTypeNode.children,
- {
- title: addproductName,
- key: `${addProductType}-${Date.now()}`,
- _raw: tempAddData
- }
-
- ];
- // // 创建新的 treeData 数组,确保 React 能够检测到更改
- const newTreeData = treeData.map(item => {
- if (item.key === addProductType) {
- return {
- ...item,
- children: newChildren,
- };
- }
- return item;
- });
- // 更新 treeData
- // setEditingProduct(null);
- setTreeData(newTreeData);
-
- let tempProductDataList = productsData[addProductType];
- tempProductDataList.push(tempAddData);
- const newProductsData = {
- ...productsData, // 假设使用了展开运算符来复制现有数组
- [addProductType]: tempProductDataList
- };
- setProductsData(newProductsData);
- setAddProductVisible(false);
- }
-
- const renderFormItem = (item) => {
- switch (item.code) {
- case "duration":
- return ;
- case "display_to_c":
- return (
-
- );
- case "dept_name":
- return ;
- case "city_name":
- return ;
- default:
- return ;
- }
- };
+ }, [activeAgency, editingProduct]);
//保存产品
const onSave = async (values) => {
- let tempInfo
- if (info.id === "") {
+ let tempInfo;
+ if (info.id === '') {
tempInfo = {
...info,
...values.info,
city_name: values.info.city_name.label,
- audit_state: "-1"
- }
+ audit_state: '-1',
+ };
delete tempInfo.product_type_name;
delete tempInfo.dept_name;
- let tempQuotation = quotation.map(element => {
+ let tempQuotation = quotation.map((element) => {
const updateData = {
...element,
- audit_state: "-1"
- }
- delete updateData.tempKey
- return updateData
- })
- let tempLgc_details = [{ ...lgc_details }]
+ audit_state: '-1',
+ };
+ delete updateData.tempKey;
+ return updateData;
+ });
+ let tempLgc_details = [{ ...lgc_details }];
const tempData = {
travel_agency_id,
info: tempInfo,
quotation: tempQuotation,
- lgc_details: Object.values(lgc_details)
+ lgc_details: Object.values(lgc_details),
};
- console.log("tempData", tempData);
+ console.log('tempData', tempData);
const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_save`, tempData);
- console.log("result", result);
+ console.log('result', result);
if (errcode === 0) {
- message.success("保存成功");
- setDataFetched(false);
+ message.success('保存成功');
} else {
message.error(`保存失败: ${result}`);
}
- return
+ return;
}
tempInfo = {
...info,
...values.info,
- audit_state: "-1"
- }
+ audit_state: '-1',
+ };
- console.log("tempInfo", tempInfo)
+ console.log('tempInfo', tempInfo);
- let tempQuotation = quotation.map(element => {
+ let tempQuotation = quotation.map((element) => {
const updateData = {
...element,
- audit_state: "-1"
- }
- return updateData
- })
-
+ audit_state: '-1',
+ };
+ return updateData;
+ });
const tempData = {
travel_agency_id,
info: tempInfo,
quotation: tempQuotation,
- lgc_details: Object.values(lgc_details)
+ lgc_details: Object.values(lgc_details),
};
- console.log("tempData", tempData)
+ console.log('tempData', tempData);
// const { errcode, result } = await postProductsSave(tempData);
const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_save`, tempData);
if (errcode === 0) {
- message.success("保存成功");
- setDataFetched(false);
+ message.success('保存成功');
} else {
message.error(`保存失败: ${result}`);
}
- return
-
+ return;
};
//提交审核方法
@@ -1055,303 +226,52 @@ const [editable, setEditable] = useState(true);
formData.append('travel_agency_id', travel_agency_id);
try {
const { errcode, result } = await postForm(`${HT_HOST}/Service_BaseInfoWeb/agency_submit`, formData);
- console.log("errcode", errcode);
+ console.log('errcode', errcode);
if (errcode === 0) {
- message.success("提交审核成功");
+ message.success('提交审核成功');
navigate(`/products/${travel_agency_id}/${use_year}/${audit_state}/audit`);
} else {
- message.error("提交审核失败");
+ message.error('提交审核失败');
}
- console.log("result", result);
+ console.log('result', result);
} catch (error) {
- console.error("提交审核请求失败", error);
- message.error("提交审核请求失败");
+ console.error('提交审核请求失败', error);
+ message.error('提交审核请求失败');
}
};
- // const handleStateChange = (newState) => {
- // console.log("newState",newState)
- // if(newState === 'addProducts'){
- // setAddProductVisible(true);
- // }
- // if(newState === 'submitReview'){
- // submitReview();
- // }
- // };
-
return (
-
- setAddProductVisible(true)} handleSubmitForAudit={submitReview} editable={editable} />
- //
+ setAddProductVisible(true)}
+ handleSubmitForAudit={submitReview}
+ editable={editable}
+ />
}>
- {isEmpty(agencyProducts) ? :
- <>
-
- {/* onNodeSelect={handleNodeSelect} */}
-
-
-
-
- {/*
*/}
- {/* */}
- {/*
-
-
-
-
- */}
- {/* */}
-
- {/* */}
-
- handleChange('title', e.target.value)}
- disabled={isCanEditable}
- />
-
-
- handleChange('description', e.target.value)}
- disabled={isCanEditable}
- />
- */}
- {/* */}
- {/* */}
-
- {/* */}
- {/* {t('products:supplierQuotation')}
*/}
- {/*
-
- {
- // !isCanEditable &&
-
- }
-
- {
-
- }
- */}
-
- {/* */}
- {/* */}
-
-
- {/* */}
-
- {/* */}
-
- {/* } onClick={() => setAddProductVisible(true)} /> */}
-{/*
- }
- >
-
- } onClick={() => setAddProductVisible(true)} />
-
-
- } onClick={async () => {
- const formData = new FormData();
- formData.append('use_year', use_year);
- formData.append('travel_agency_id', travel_agency_id);
- const { errcode, result } = await postForm(`${HT_HOST}/Service_BaseInfoWeb/agency_submit`, formData);
- console.log("errcode", errcode);
- if (errcode === 0) {
- message.success("提交审核成功");
- navigate(`/products/${travel_agency_id}/${use_year}/${audit_state}/audit`);
- }
- console.log("result", result);
- }} />
-
- */}
- {/* */}
- {/*
*/}
-
-
-
- {/* setBatchImportPriceVisible(false)}
- width={'90%'}
- >
-
- */}
-
- setAddProductVisible(false)}
- >
- 选择产品类别
-
-
-
- 新增产品名称
- setAddProductName(e.target.value)}
- />
-
-{/*
-
- 成人价
- setCurrentQuotationRecord({ ...currentQuotationRecord, adult_cost: e })} />
- 儿童价
- setCurrentQuotationRecord({ ...currentQuotationRecord, child_cost: e })} />
- 币种
-
- 类型
-
-
- 人等
-
- setCurrentQuotationRecord({ ...currentQuotationRecord, group_size_min: e })}
- style={{ width: '50%', marginRight: '10px' }}
- />
- -
- setCurrentQuotationRecord({ ...currentQuotationRecord, group_size_max: e })}
- style={{ width: '50%', marginLeft: '10px' }}
- />
- |
- 有效期
- {
- setCurrentQuotationRecord({
- ...currentQuotationRecord,
- use_dates_start: dates[0],
- use_dates_end: dates[1]
- });
- }}
- />
- 周末
- {days.map((day, index) => (
-
- ))}
- */}
- >}
-
+ {isEmpty(agencyProducts) ? (
+
+ ) : (
+ <>
+
+ {/* onNodeSelect={handleNodeSelect} */}
+
+
+
+
+
+ setAddProductVisible(false)} onCancel={() => setAddProductVisible(false)} />
+
+ >
+ )}
+
);
}
export default Detail;
-
-
diff --git a/src/views/products/Detail/NewProductModal.jsx b/src/views/products/Detail/NewProductModal.jsx
new file mode 100644
index 0000000..538e673
--- /dev/null
+++ b/src/views/products/Detail/NewProductModal.jsx
@@ -0,0 +1,115 @@
+import { useState, useEffect } from 'react';
+import { Form, Modal, Input } from 'antd';
+import { objectMapper } from '@/utils/commons';
+import { useTranslation } from 'react-i18next';
+
+import ProductsTypesSelector from '@/components/ProductsTypesSelector';
+import useProductsStore from '@/stores/Products/Index';
+import { useNewProductRecord, useProductsTypesMapVal } from '@/hooks/useProductsSets';
+import { useDefaultLgc } from '@/i18n/LanguageSwitcher';
+
+export const NewProductsForm = ({ initialValues, onFormInstanceReady, ...props }) => {
+ const { t } = useTranslation();
+ const [form] = Form.useForm();
+
+ useEffect(() => {
+ onFormInstanceReady(form);
+ }, []);
+
+ const onValuesChange = (changeValues, allValues) => {};
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+const formValuesMapper = (values) => {
+ const destinationObject = {
+ 'products_types': {
+ key: 'products_types',
+ transform: (value) => {
+ return Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? value.value : '-1';
+ },
+ },
+ };
+ let dest = {};
+ const { ...omittedValue } = values;
+ dest = { ...omittedValue, ...objectMapper(values, destinationObject) };
+ for (const key in dest) {
+ if (Object.prototype.hasOwnProperty.call(dest, key)) {
+ dest[key] = typeof dest[key] === 'string' ? (dest[key] || '').trim() : dest[key];
+ }
+ }
+ // omit empty
+ // Object.keys(dest).forEach((key) => (dest[key] == null || dest[key] === '' || dest[key].length === 0) && delete dest[key]);
+ return dest;
+};
+/**
+ *
+ */
+export const NewProductModal = ({ source, action = '#' | 'o', open, onSubmit, onCancel, initialValues }) => {
+ const { t } = useTranslation();
+ const [formInstance, setFormInstance] = useState();
+ const [setEditingProduct] = useProductsStore((state) => [state.setEditingProduct]);
+
+ const [copyLoading, setCopyLoading] = useState(false);
+ const productsTypesMapVal = useProductsTypesMapVal();
+ const newProduct = useNewProductRecord();
+ const { language } = useDefaultLgc();
+ const handelAddProduct = (param) => {
+ const copyNewProduct = structuredClone(newProduct);
+ copyNewProduct.info.title = param.title;
+ copyNewProduct.info.product_type_id = productsTypesMapVal[param.products_type.value].value;
+ copyNewProduct.info.product_type_name = productsTypesMapVal[param.products_type.value].label;
+ copyNewProduct.lgc_details[0].lgc = language;
+ copyNewProduct.lgc_details[0].title = param.title;
+ setEditingProduct(copyNewProduct);
+ if (typeof onSubmit === 'function') {
+ onSubmit();
+ }
+ return false;
+ };
+ return (
+ <>
+ {
+ onCancel();
+ formInstance?.resetFields();
+ }}
+ destroyOnClose
+ onOk={async () => {
+ try {
+ const values = await formInstance?.validateFields();
+ // formInstance?.resetFields();
+ const dest = formValuesMapper(values);
+ handelAddProduct(dest);
+ } catch (error) {
+ console.log('Failed:', error);
+ }
+ }}>
+ {
+ setFormInstance(instance);
+ }}
+ />
+
+ >
+ );
+};
+export default NewProductModal;
diff --git a/src/views/products/Detail/ProductInfoForm.jsx b/src/views/products/Detail/ProductInfoForm.jsx
index 840d9c7..4472b26 100644
--- a/src/views/products/Detail/ProductInfoForm.jsx
+++ b/src/views/products/Detail/ProductInfoForm.jsx
@@ -22,7 +22,7 @@ import { PERM_PRODUCTS_MANAGEMENT, PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFE
const { RangePicker } = DatePicker;
-const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, showSubmit, confirmText, formName, loading, ...props }) => {
+const InfoForm = ({ onSubmit, onReset, onValuesChange, editable, showSubmit, confirmText, formName, loading, ...props }) => {
const { t } = useTranslation('products');
const isPermitted = useAuthStore((state) => state.isPermitted);
const [agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.agencyProducts, state.editingProduct, state.setEditingProduct]);
@@ -49,7 +49,9 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
return () => {};
}, [editingProduct?.info?.id]);
- const ignoreEditable = isPermitted(PERM_PRODUCTS_OFFER_AUDIT);
+ const topPerm = isPermitted(PERM_PRODUCTS_OFFER_AUDIT);
+ const isNew = isEmpty(editingProduct?.info?.id);
+ const ignoreEditable = topPerm || isNew;
const onFinish = (values) => {
console.log('Received values of form, origin form value: \n', values);