diff --git a/package.json b/package.json index ac1a9b2..f2ea881 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "global-highlights-hub", "private": true, - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "type": "module", "scripts": { "dev": "vite", diff --git a/public/locales/en/common.json b/public/locales/en/common.json index b228ae8..f5dd835 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -29,6 +29,7 @@ "sureCancel": "Are you sure to cancel?", "sureDelete":"Are you sure to delete?", "Yes": "Yes", + "No": "No", "Success": "Success", "Failed": "Failed", diff --git a/public/locales/en/products.json b/public/locales/en/products.json index 384e1f5..50bda51 100644 --- a/public/locales/en/products.json +++ b/public/locales/en/products.json @@ -98,6 +98,7 @@ "CopyFormMsg": { "Source": "Source ", "target": "Target ", + "withQuote": "Whether to copy the quotation", "requiredVendor": "Please pick a target vendor", "requiredTypes": "Please select product types", "requiredDept": "Please pick a owner department" diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index dd6e73e..5c120b0 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -29,6 +29,7 @@ "sureCancel": "确定取消?", "sureDelete":"确定删除?", "Yes": "是", + "No": "否", "Success": "成功", "Failed": "失败", diff --git a/public/locales/zh/products.json b/public/locales/zh/products.json index c8b56a4..2c5ae72 100644 --- a/public/locales/zh/products.json +++ b/public/locales/zh/products.json @@ -98,6 +98,7 @@ "CopyFormMsg": { "Source": "源", "target": "目标", + "withQuote": "是否复制报价", "requiredVendor": "请选择目标供应商", "requiredTypes": "请选择产品类型", "requiredDept": "请选择所属小组" diff --git a/src/components/BackBtn.jsx b/src/components/BackBtn.jsx index 26068e0..baefd53 100644 --- a/src/components/BackBtn.jsx +++ b/src/components/BackBtn.jsx @@ -9,7 +9,7 @@ const BackBtn = ({to, ...props}) => { const navigate = useNavigate(); return ( <> - {isNotEmpty(to) ? {t('Back')} : } + {isNotEmpty(to) ? {t('Back')} : } ); }; diff --git a/src/components/ProductsTypesSelector.jsx b/src/components/ProductsTypesSelector.jsx index ca61815..6c719fe 100644 --- a/src/components/ProductsTypesSelector.jsx +++ b/src/components/ProductsTypesSelector.jsx @@ -2,15 +2,6 @@ import { Select } from 'antd'; import { useProductsTypes } from '@/hooks/useProductsSets'; import { useTranslation } from 'react-i18next'; -import { fetchJSON } from '@/utils/request'; -import { HT_HOST } from '@/config'; - -//供应商列表 -export const fetchVendorList = async (q) => { - const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/VendorList`, { q }) - return errcode !== 0 ? [] : result -} - const ProductsTypesSelector = ({...props}) => { const productsTypes = useProductsTypes(); const { t } = useTranslation(); diff --git a/src/components/SearchForm.jsx b/src/components/SearchForm.jsx index ab0be78..89b79b9 100644 --- a/src/components/SearchForm.jsx +++ b/src/components/SearchForm.jsx @@ -9,8 +9,9 @@ import { useTranslation } from 'react-i18next'; import SearchInput from './SearchInput'; import AuditStateSelector from './AuditStateSelector'; import DeptSelector from './DeptSelector'; -import ProductsTypesSelector, { fetchVendorList } from './ProductsTypesSelector'; +import ProductsTypesSelector from './ProductsTypesSelector'; import CitySelector from '@/components/CitySelector'; +import VendorSelector from '@/components/VendorSelector'; const { RangePicker } = DatePicker; @@ -248,14 +249,7 @@ function getFields(props) { 'agency', 99, - + , fieldProps?.agency?.col || 6 ), diff --git a/src/components/SecondHeaderWrapper.jsx b/src/components/SecondHeaderWrapper.jsx index 9a4f7bd..b456bca 100644 --- a/src/components/SecondHeaderWrapper.jsx +++ b/src/components/SecondHeaderWrapper.jsx @@ -3,7 +3,7 @@ import { Layout, Flex, theme, Spin, Divider } from 'antd'; import BackBtn from './BackBtn'; const { Content, Header } = Layout; -const HeaderWrapper = ({ children, header, loading, ...props }) => { +const HeaderWrapper = ({ children, header, loading, backTo, ...props }) => { const navigate = useNavigate(); const { token: { colorBgContainer }, @@ -16,7 +16,7 @@ const HeaderWrapper = ({ children, header, loading, ...props }) => { {/* {header} */}
{header}
- +
diff --git a/src/components/VendorSelector.jsx b/src/components/VendorSelector.jsx new file mode 100644 index 0000000..639db96 --- /dev/null +++ b/src/components/VendorSelector.jsx @@ -0,0 +1,29 @@ +import { createContext, useEffect, useState } from 'react'; +import {} from 'antd'; +import SearchInput from './SearchInput'; +import { fetchJSON } from '@/utils/request'; +import { HT_HOST } from '@/config'; +import { useTranslation } from 'react-i18next'; + +//供应商列表 +export const fetchVendorList = async (q) => { + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/VendorList`, { q }); + return errcode !== 0 ? [] : result; +}; + +const VendorSelector = ({ ...props }) => { + const { t } = useTranslation(); + return ( + <> + + + ); +}; +export default VendorSelector; diff --git a/src/hooks/useProductsSets.js b/src/hooks/useProductsSets.js index 6f7fbe5..8c3ea2b 100644 --- a/src/hooks/useProductsSets.js +++ b/src/hooks/useProductsSets.js @@ -52,7 +52,7 @@ export const useProductsTypes = (showAll = false) => { { label: t('products:type.UltraService'), value: 'B', key: 'B' }, { label: t('products:type.Car'), value: 'J', key: 'J' }, { label: t('products:type.Guide'), value: 'Q', key: 'Q' }, - { label: t('products:type.Attractions'), value: '7', key: '7' }, + { label: t('products:type.Attractions'), value: '7', key: '7' }, // landscape { label: t('products:type.Meals'), value: 'R', key: 'R' }, { label: t('products:type.Extras'), value: '8', key: '8' }, { label: t('products:type.Package'), value: 'D', key: 'D' }, diff --git a/src/stores/Airticket.js b/src/stores/Airticket.js index 6a393b9..e73711a 100644 --- a/src/stores/Airticket.js +++ b/src/stores/Airticket.js @@ -30,8 +30,8 @@ const airTicketStore = create((set, get) => ({ async getPlanDetail(vei_sn, gri_sn) { const { setPlanDetail } = get(); const searchParams = { - vei_sn: 6376, //vei_sn, - gri_sn: 369040, //gri_sn + vei_sn: 4272, //vei_sn, + gri_sn: 372928, //gri_sn }; const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetFlightPlanDetail`, searchParams); const _result = errcode !== 0 ? [] : result; diff --git a/src/stores/Products/Index.js b/src/stores/Products/Index.js index a06850e..3d727be 100644 --- a/src/stores/Products/Index.js +++ b/src/stores/Products/Index.js @@ -30,7 +30,7 @@ export const copyAgencyDataAction = async (postbody) => { }; export const getAgencyProductsAction = async (param) => { - const _param = { ...param, use_year: (param.use_year || '').replace('all', ''), audit_state: (param.audit_state || '').replace('all', '') }; + const _param = { ...param, use_year: String(param.use_year || '').replace('all', ''), audit_state: (param.audit_state || '').replace('all', '') }; const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/travel_agency_products`, _param); return errcode !== 0 ? { agency: {}, products: [] } : result; }; @@ -39,6 +39,7 @@ export const getAgencyProductsAction = async (param) => { * */ export const addProductExtraAction = async (body) => { + console.log('addProductExtraAction', body); return true; // test: 先不更新到HT const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/products_extras_add`, body); return errcode === 0 ? true : false; diff --git a/src/views/account/Management.jsx b/src/views/account/Management.jsx index 7081be3..f495de5 100644 --- a/src/views/account/Management.jsx +++ b/src/views/account/Management.jsx @@ -128,6 +128,7 @@ function Management() { const onAccountFinish = (values) => { saveOrUpdateAccount(values) .then(() => { + setAccountModalOpen(false) handelAccountSearch() }) .catch(ex => { @@ -224,7 +225,7 @@ function Management() { htmlType: 'submit', }} title={t('account:detail')} - open={isAccountModalOpen} onOk={() => setAccountModalOpen(false)} onCancel={() => setAccountModalOpen(false)} + open={isAccountModalOpen} onCancel={() => setAccountModalOpen(false)} destroyOnClose forceRender modalRender={(dom) => ( diff --git a/src/views/account/RoleList.jsx b/src/views/account/RoleList.jsx index 796aafe..5143081 100644 --- a/src/views/account/RoleList.jsx +++ b/src/views/account/RoleList.jsx @@ -132,6 +132,7 @@ function RoleList() { const onRoleFinish = (values) => { saveOrUpdateRole(values) .then(() => { + setRoleModalOpen(false) fetchRoleList() .then(r => { setRoleAllList(r) @@ -148,6 +149,7 @@ function RoleList() { } const onRoleFailed = (error) => { + console.log('Failed:', error) // form.resetFields() } @@ -160,7 +162,7 @@ function RoleList() { htmlType: 'submit', }} title={t('account:detail')} - open={isRoleModalOpen} onOk={() => setRoleModalOpen(false)} onCancel={() => setRoleModalOpen(false)} + open={isRoleModalOpen} onCancel={() => setRoleModalOpen(false)} destroyOnClose forceRender modalRender={(dom) => ( diff --git a/src/views/airticket/Plan.jsx b/src/views/airticket/Plan.jsx index 29ba956..ea193fa 100644 --- a/src/views/airticket/Plan.jsx +++ b/src/views/airticket/Plan.jsx @@ -1,5 +1,5 @@ import { useState, useEffect } from "react"; -import { Grid, Divider, Layout, Form, Input, Col, Row, Space, Collapse, Table, Button } from "antd"; +import { Grid, Divider, Layout, Modal, Form, Input, Col, Row, Space, Collapse, Table, Button, Select, InputNumber, Typography } from "antd"; import { PhoneOutlined, CustomerServiceOutlined, AudioOutlined, ArrowUpOutlined, ArrowDownOutlined } from "@ant-design/icons"; import { useParams, useHref, useNavigate, NavLink } from "react-router-dom"; import { isEmpty, formatColonTime } from "@/utils/commons"; @@ -15,14 +15,96 @@ const AirticketPlan = props => { const reservationUrl = `https://p9axztuwd7x8a7.mycht.cn/Service_BaseInfoWeb/FlightPlanDocx?GRI_SN=${coli_sn}&VEI_SN=${travelAgencyId}`; const reservationPreviewUrl = OFFICEWEBVIEWERURL + encodeURIComponent(reservationUrl); - console.log(reservationPreviewUrl); + // console.log(reservationPreviewUrl); + + //乘客列表 + const guestListColumns = [ + { + title: "姓名", + key: "MEI_Name", + dataIndex: "MEI_Name", + }, + { + title: "证件类型", + key: "MEI_PassportType", + dataIndex: "MEI_PassportType", + }, + { + title: "证件号", + key: "MEI_PassportNo", + dataIndex: "MEI_PassportNo", + }, + { + title: "证件有效期", + key: "MEI_PassportValidDate", + dataIndex: "MEI_PassportValidDate", + }, + { + title: "性别", + key: "MEI_Gender", + dataIndex: "MEI_Gender", + }, + { + title: "年龄", + key: "MEI_age", + dataIndex: "MEI_age", + }, + { + title: "国籍", + key: "MEI_Country", + dataIndex: "MEI_Country", + }, + { + title: "票号", + key: "MEI_SN", + dataIndex: "MEI_SN", + }, + { + title: "PNR", + key: "MEI_SN", + dataIndex: "MEI_SN", + }, + { + title: "机票费用(RMB)含基建和税", + key: "MEI_SN", + dataIndex: "MEI_SN", + }, + { + title: "折扣", + key: "MEI_SN", + dataIndex: "MEI_SN", + }, + { + title: "手续费", + key: "MEI_SN", + dataIndex: "MEI_SN", + }, + { + title: "机票类型(成人/儿童/婴儿)", + key: "MEI_SN", + dataIndex: "MEI_SN", + }, + { + title: "操作", + key: "MEI_SN", + dataIndex: "MEI_SN", + render: (_, record) => { + return ( + + showModal(record)}>编辑 | console.log("del")}>删除 + + ); + }, + }, + ]; const Airticket_form = props => { const aitInfo = props.airInfo; return ( <>
{ // onFinish={onFinish} // onFinishFailed={onFinishFailed} autoComplete="off"> - - - - } value={aitInfo.FromCity} /> } value={aitInfo.ToCity} /> - + + @@ -74,18 +153,24 @@ const AirticketPlan = props => { - {/* - - */} + + + + + + + 费用列表 + - -
); }; @@ -102,73 +187,146 @@ const AirticketPlan = props => { : []; }; - const guestListColumns = [ - { - title: "姓名", - key: "MEI_Name", - dataIndex: "MEI_Name", - }, - { - title: "证件类型", - key: "MEI_PassportType", - dataIndex: "MEI_PassportType", - }, - { - title: "证件号", - key: "MEI_PassportNo", - dataIndex: "MEI_PassportNo", - }, - { - title: "证件有效期", - key: "MEI_PassportValidDate", - dataIndex: "MEI_PassportValidDate", - }, - { - title: "性别", - key: "MEI_Gender", - dataIndex: "MEI_Gender", - }, - { - title: "年龄", - key: "MEI_age", - dataIndex: "MEI_age", - }, - { - title: "国籍", - key: "MEI_Country", - dataIndex: "MEI_Country", - }, - { - title: "票号", - key: "MEI_SN", - dataIndex: "MEI_SN", - }, - { - title: "PNR", - key: "MEI_SN", - dataIndex: "MEI_SN", - }, - { - title: "机票费用(RMB)含基建和税", - key: "MEI_SN", - dataIndex: "MEI_SN", - }, - { - title: "折扣", - key: "MEI_SN", - dataIndex: "MEI_SN", - }, - { - title: "手续费", - key: "MEI_SN", - dataIndex: "MEI_SN", - }, - { - title: "机票类型(成人/儿童/婴儿)", - key: "MEI_SN", - dataIndex: "MEI_SN", - }, - ]; + // 机票信息编辑表单 begin + const [isModalOpen, setIsModalOpen] = useState(false); + const [ticket_form] = Form.useForm(); + + const showModal = ticket => { + setIsModalOpen(true); + ticket_form.setFieldsValue(ticket); + }; + + const handleOk = () => { + ticket_form + .validateFields() + .then(values => { + // 在这里处理表单提交逻辑,例如发送数据到服务器 + console.log("Received values of form: ", values); + ticket_form.resetFields(); + setIsModalOpen(false); + }) + .catch(info => { + console.log("Validate Failed:", info); + }); + }; + + const handleCancel = () => { + ticket_form.resetFields(); + setIsModalOpen(false); + }; + + const onChangeType = value => { + console.log(value); + }; + + const TicketModal = () => { + return ( + <> + +
+ + console.log("dsads")} + options={[ + { + value: "jack", + label: "成人", + }, + { + value: "lucy", + label: "儿童", + }, + { + value: "Yiminghe", + label: "婴儿", + }, + ]} + /> + + + + + + + + + + + + + + + + + + + + + + {/* + {(use_year || '').replace('all', '')} */} {/* */} {/* */} - + {t('Edit')} - @@ -60,7 +103,7 @@ const Header = ({ title, agency, refresh, ...props }) => { {t('products:auditStateAction.Approved')} */} - @@ -216,27 +259,22 @@ const TypesPanels = (props) => { const onCollapseChange = (_activeKey) => { setActiveKey(_activeKey); }; - return ; + return isEmpty(agencyProducts) ? : ; }; const Audit = ({ ...props }) => { const { travel_agency_id, use_year, audit_state } = useParams(); const [loading, activeAgency, getAgencyProducts] = useProductsStore((state) => [state.loading, state.activeAgency, state.getAgencyProducts]); - const handleGetAgencyProducts = () => { - getAgencyProducts({ travel_agency_id, use_year, audit_state }); + const handleGetAgencyProducts = ({pick_year, pick_agency}={}) => { + const year = pick_year || use_year; + const agency = pick_agency || travel_agency_id; + getAgencyProducts({ travel_agency_id: agency, use_year: year, audit_state }); }; - useEffect(() => { - handleGetAgencyProducts(); - - return () => {}; - }, [travel_agency_id]); - return ( <> - } loading={loading} > - {/* debug: 0 */} + } loading={loading} backTo={`/products`}> {/* */} diff --git a/src/views/products/Detail/CopyProducts.jsx b/src/views/products/Detail/CopyProducts.jsx index 6b4d151..af2ed57 100644 --- a/src/views/products/Detail/CopyProducts.jsx +++ b/src/views/products/Detail/CopyProducts.jsx @@ -1,11 +1,12 @@ import { useState, useEffect } from 'react'; -import { App, Form, Modal, DatePicker, Divider } from 'antd'; +import { App, Form, Modal, DatePicker, Divider, Switch } from 'antd'; import { isEmpty, objectMapper } from '@/utils/commons'; import { useTranslation } from 'react-i18next'; import SearchInput from '@/components/SearchInput'; import DeptSelector from '@/components/DeptSelector'; -import ProductsTypesSelector, { fetchVendorList } from '@/components/ProductsTypesSelector'; +import ProductsTypesSelector from '@/components/ProductsTypesSelector'; +import { fetchVendorList } from '@/components/VendorSelector'; import dayjs from 'dayjs'; import arraySupport from 'dayjs/plugin/arraySupport'; import { copyAgencyDataAction } from '@/stores/Products/Index'; @@ -28,7 +29,7 @@ export const CopyProductsForm = ({ action, initialValues, onFormInstanceReady, s const onValuesChange = (changeValues, allValues) => {}; return ( - + {action === '#' && } - + {action === '#' && @@ -46,11 +47,15 @@ export const CopyProductsForm = ({ action, initialValues, onFormInstanceReady, s } - + - - current <= dayjs([source.sourceYear, 12, 31])} /> + + + {/* disabledDate={(current) => current <= dayjs([source.sourceYear, 12, 31])} */} + + + ); @@ -68,7 +73,7 @@ const formValuesMapper = (values) => { 'products_types': { key: 'products_types', transform: (value) => { - return Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? value.value : ''; + return Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? value.value : '-1'; }, }, 'dept': { @@ -77,6 +82,7 @@ const formValuesMapper = (values) => { return Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? value.value : ''; }, }, + 'with_quote': { key: 'with_quote', transform: (value) => (value ? 1 : 0) }, }; let dest = {}; const { agency, year, ...omittedValue } = values; diff --git a/src/views/products/Manage.jsx b/src/views/products/Manage.jsx index 1aa105c..4b2f2b6 100644 --- a/src/views/products/Manage.jsx +++ b/src/views/products/Manage.jsx @@ -6,9 +6,12 @@ import dayjs from 'dayjs'; import arraySupport from 'dayjs/plugin/arraySupport'; import { useTranslation } from 'react-i18next'; import useProductsStore, { copyAgencyDataAction } from '@/stores/Products/Index'; +import { useProductsTypes, useProductsAuditStatesMapVal } from '@/hooks/useProductsSets'; import useFormStore from '@/stores/Form'; import { objectMapper } from '@/utils/commons'; import CopyProductsFormModal from './Detail/CopyProducts'; +import useAuthStore from '@/stores/Auth'; +import RequireAuth from '@/components/RequireAuth'; dayjs.extend(arraySupport); @@ -20,6 +23,8 @@ function Index() { const [searchValues, setSearchValues] = useProductsStore((state) => [state.searchValues, state.setSearchValues]); const formValuesToSub = useFormStore(state => state.formValuesToSub); + const stateMapVal = useProductsAuditStatesMapVal(); + const useYear = formValuesToSub.year; const handleSearchAgency = (formVal = undefined) => { @@ -60,7 +65,15 @@ function Index() { { title: t('products:Vendor'), key: 'vendor', dataIndex: 'travel_agency_name' }, { title: t('products:CreatedBy'), key: 'poster_by', dataIndex: 'poster_name' }, { title: t('products:CreateDate'), key: 'poster_date', dataIndex: 'poster_date' }, - { title: t('products:AuState'), key: 'audit_state', dataIndex: 'audit_state' }, + { + title: t('products:AuState'), + key: 'audit_state', + dataIndex: 'audit_state', + render: (_, r) => { + const stateCls = ` text-${stateMapVal[`${r.audit_state_id}`]?.color} `; + return {stateMapVal[`${r.audit_state_id}`]?.label}; + }, + }, { title: t('products:AuditedBy'), key: 'audited_by', dataIndex: 'audited_by_name' }, { title: t('products:AuditDate'), key: 'audit_date', dataIndex: 'audit_date' }, { @@ -69,9 +82,15 @@ function Index() { render: (_, r) => ( {t('Edit')} - {t('Audit')} - - + {r.audit_state_id >= 0 ? ( + {t('Audit')} + ) : ( + {t('Audit')} + )} + + {/* */} ), }, @@ -102,6 +121,7 @@ function Index() { {/* 复制弹窗 */}