feat: 产品管理: 搜索+年份,状态; 产品类型排序; 审核页: 成人,儿童价; 语种列表

feature/price_manager
Lei OT 1 year ago
parent a61ef8882b
commit e9b7aec521

@ -7,6 +7,7 @@
"Attractions": "Attractions", "Attractions": "Attractions",
"Meals": "Meals", "Meals": "Meals",
"Extras": "Extras", "Extras": "Extras",
"Overtravel": "超公里",
"Special": "Special" "Special": "Special"
}, },
"auditState": { "auditState": {
@ -20,7 +21,7 @@
"New": "New", "New": "New",
"Pending": "Pending", "Pending": "Pending",
"Approved": "Approve", "Approved": "Approve",
"Rejected": "Rejecte", "Rejected": "Reject",
"Published": "Publish" "Published": "Publish"
}, },
"Status": "Status", "Status": "Status",
@ -42,6 +43,8 @@
"UseDates": "Use Dates", "UseDates": "Use Dates",
"Weekdays": "Weekdays", "Weekdays": "Weekdays",
"UseYear": "Use Year",
"AgeType": { "AgeType": {
"Type": "Age Type", "Type": "Age Type",
"Adult": "Adult", "Adult": "Adult",

@ -6,7 +6,8 @@
"Package": "包价线路", "Package": "包价线路",
"Attractions": "景点", "Attractions": "景点",
"Meals": "餐费", "Meals": "餐费",
"Extras": "附加", "Extras": "附加项目",
"Overtravel": "超公里",
"Special": "特殊项目" "Special": "特殊项目"
}, },
"auditState": { "auditState": {
@ -21,7 +22,7 @@
"Pending": "待审核", "Pending": "待审核",
"Approved": "审核通过", "Approved": "审核通过",
"Rejected": "审核拒绝", "Rejected": "审核拒绝",
"Published": "发布上线" "Published": "审核发布"
}, },
"Status": "状态", "Status": "状态",
"State": "状态", "State": "状态",
@ -41,6 +42,8 @@
"UseDates": "使用日期", "UseDates": "使用日期",
"Weekdays": "有效日/周X", "Weekdays": "有效日/周X",
"UseYear": "年份",
"AgeType": { "AgeType": {
"Type": "人群", "Type": "人群",
"Adult": "成人", "Adult": "成人",

@ -3,7 +3,7 @@ import { Form, Input, Row, Col, Select, DatePicker, Space, Button } from 'antd';
import { objectMapper, at } from '@/utils/commons'; import { objectMapper, at } from '@/utils/commons';
import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from '@/config'; import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from '@/config';
import useFormStore from '@/stores/Form'; import useFormStore from '@/stores/Form';
import usePresets from '@/hooks/usePresets'; import useDatePresets from '@/hooks/useDatePresets';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { fetchJSON } from '@/utils/request'; import { fetchJSON } from '@/utils/request';
@ -14,8 +14,8 @@ import AuditStateSelector from './AuditStateSelector';
// //
export const fetchVendorList = async () => { export const fetchVendorList = async (q) => {
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/VendorList`) const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/VendorList`, { q })
return errcode !== 0 ? [] : result return errcode !== 0 ? [] : result
} }
@ -23,7 +23,7 @@ const { RangePicker } = DatePicker;
const SearchForm = ({ initialValue, onSubmit, onReset, ...props }) => { const SearchForm = ({ initialValue, onSubmit, onReset, ...props }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const presets = usePresets(); const presets = useDatePresets();
const [formValues, setFormValues] = useFormStore((state) => [state.formValues, state.setFormValues]); const [formValues, setFormValues] = useFormStore((state) => [state.formValues, state.setFormValues]);
const [formValuesToSub, setFormValuesToSub] = useFormStore((state) => [state.formValuesToSub, state.setFormValuesToSub]); const [formValuesToSub, setFormValuesToSub] = useFormStore((state) => [state.formValuesToSub, state.setFormValuesToSub]);
const [form] = Form.useForm(); const [form] = Form.useForm();
@ -57,6 +57,9 @@ const SearchForm = ({ initialValue, onSubmit, onReset, ...props }) => {
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 : '';
}, },
}, },
'year': [
{ key: 'year', transform: (arrVal) => (arrVal ? arrVal.format('YYYY') : '') },
],
}; };
let dest = {}; let dest = {};
const { dates, ...omittedValue } = values; const { dates, ...omittedValue } = values;
@ -165,15 +168,15 @@ function getFields(props) {
'referenceNo', 'referenceNo',
99, 99,
<Form.Item name='referenceNo' label={t('group:RefNo')} {...fieldProps.referenceNo}> <Form.Item name='referenceNo' label={t('group:RefNo')} {...fieldProps.referenceNo}>
<Input placeholder={t('group:RefNo')} allowClear /> <Input placeholder={t('group:RefNo')} allowClear />
</Form.Item>, </Form.Item>,
fieldProps?.referenceNo?.col || 6 fieldProps?.referenceNo?.col || 6
), ),
item( item(
'PNR', 'PNR',
99, 99,
<Form.Item name='PNR' label="PNR"> <Form.Item name='PNR' label='PNR'>
<Input placeholder={t('group:PNR')} allowClear /> <Input placeholder={t('group:PNR')} allowClear />
</Form.Item>, </Form.Item>,
fieldProps?.PNR?.col || 4 fieldProps?.PNR?.col || 4
), ),
@ -208,11 +211,26 @@ function getFields(props) {
/** /**
* *
*/ */
item(
'year',
99,
<Form.Item name={'year'} label={t('products:UseYear')} {...fieldProps.year} initialValue={at(props, 'initialValue.year')[0]}>
<DatePicker picker='year' allowClear {...fieldComProps.year} />
</Form.Item>,
fieldProps?.year?.col || 3
),
item( item(
'agency', 'agency',
99, 99,
<Form.Item name='agency' label={t('products:Vendor')} {...fieldProps.agency} initialValue={at(props, 'initialValue.agency')[0]}> <Form.Item name='agency' label={t('products:Vendor')} {...fieldProps.agency} initialValue={at(props, 'initialValue.agency')[0]}>
<SearchInput placeholder={t('products:Vendor')} mode={'multiple'} maxTagCount={0} {...fieldComProps.agency} fetchOptions={fetchVendorList} map={{travel_agency_name: 'label', travel_agency_id: 'value'}} /> <SearchInput
placeholder={t('products:Vendor')}
mode={'multiple'}
maxTagCount={0}
{...fieldComProps.agency}
fetchOptions={fetchVendorList}
map={{ travel_agency_name: 'label', travel_agency_id: 'value' }}
/>
</Form.Item>, </Form.Item>,
fieldProps?.agency?.col || 6 fieldProps?.agency?.col || 6
), ),
@ -224,7 +242,6 @@ function getFields(props) {
</Form.Item>, </Form.Item>,
fieldProps?.audit_state?.col || 3 fieldProps?.audit_state?.col || 3
), ),
]; ];
baseChildren = baseChildren baseChildren = baseChildren
.map((x) => { .map((x) => {

@ -31,6 +31,7 @@ function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
showSearch showSearch
allowClear allowClear
maxTagCount={1} maxTagCount={1}
dropdownStyle={{width: '16rem'}}
{...props} {...props}
onSearch={debounceFetcher} onSearch={debounceFetcher}
notFoundContent={fetching ? <Spin size='small' /> : null} notFoundContent={fetching ? <Spin size='small' /> : null}

@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
const usePresets = () => { const useDatePresets = () => {
const [presets, setPresets] = useState([]); const [presets, setPresets] = useState([]);
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
@ -39,4 +39,4 @@ const usePresets = () => {
return presets; return presets;
} }
export default usePresets; export default useDatePresets;

@ -0,0 +1,14 @@
export const useLanguageSets = () => {
const newData = [
{ key: '1', value: '1', label: 'English' },
{ key: '2', value: '2', label: 'Chinese (中文)' },
{ key: '3', value: '3', label: 'Japanese (日本語)' },
{ key: '4', value: '4', label: 'German (Deutsch)' },
{ key: '5', value: '5', label: 'French (Français)' },
{ key: '6', value: '6', label: 'Spanish (Español)' },
{ key: '7', value: '7', label: 'Russian (Русский)' },
{ key: '8', value: '8', label: 'Italian (Italiano)' },
];
return newData;
};

@ -27,6 +27,7 @@ export const useProductsTypes = () => {
useEffect(() => { useEffect(() => {
const newData = [ const newData = [
{ label: t('products:type.Experience'), value: '6', key: '6' }, { label: t('products:type.Experience'), value: '6', key: '6' },
{ label: t('products:type.Overtravel'), value: 'B', key: 'B' },
{ label: t('products:type.Car'), value: 'Car', key: 'Car' }, { label: t('products:type.Car'), value: 'Car', key: 'Car' },
{ label: t('products:type.Guide'), value: 'Guide', key: 'Guide' }, { label: t('products:type.Guide'), value: 'Guide', key: 'Guide' },
{ label: t('products:type.Package'), value: 'D', key: 'D' }, { label: t('products:type.Package'), value: 'D', key: 'D' },

@ -69,8 +69,8 @@ const router = createBrowserRouter([
{ path: "invoice/paid/detail/:flid",element:<InvoicePaidDetail />}, { path: "invoice/paid/detail/:flid",element:<InvoicePaidDetail />},
{ path: "airticket",element:<Airticket />}, { path: "airticket",element:<Airticket />},
{ path: "products",element:<ProductsIndex />}, { path: "products",element:<ProductsIndex />},
{ path: "products/:travel_agency_id/audit",element:<ProductsAudit />}, { path: "products/:travel_agency_id/:use_year/:audit_state/audit",element:<ProductsAudit />},
{ path: "products/:travel_agency_id",element:<ProductsDetail />}, { path: "products/:travel_agency_id/:use_year/:audit_state/edit",element:<ProductsDetail />},
] ]
}, },
{ {

@ -10,7 +10,8 @@ export const searchAgencyAction = async (param) => {
return errcode !== 0 ? [] : result; return errcode !== 0 ? [] : result;
}; };
export const getAgencyProductsAction = async (param) => { export const getAgencyProductsAction = async (param) => {
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/travel_agency_products`, param); const _param = { ...param, use_year: (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; return errcode !== 0 ? { agency: {}, products: [] } : result;
}; };
@ -47,238 +48,10 @@ export const postProductsAudit = async (auditState, infoRow) => {
const initialState = { const initialState = {
loading: false, loading: false,
searchValues: {},
agencyList: [], agencyList: [],
activeAgency: {}, activeAgency: {},
agencyProducts: groupBy([ agencyProducts: {},
{
"info": {
"id": "640000198509289851",
"title": "如拉下完公",
"code": "grlkt",
"type": "Guide",
"audit_state": "1",
"create_date": "2022-01-13",
"created_by": "郝涛",
"travel_agency_id": "710000200712195349",
"travel_agency_name": "国得气验",
"lastedit_memo": "划百引程级门会需代领主属快。",
"remarks": "及决对金利低集小理电和按常如门。",
"duration": 2,
"duration_unit": "m",
"open_weekdays": "6",
"recommends_rate": 3,
"dept": 1,
"display_to_c": "2",
"km": 27,
"city_id": 77,
"city_name": "称命"
},
"quotation": [
{
"id": "21000020030611324X",
"value": 70,
"currency": "CNY",
"unit": "团",
"age_type": "儿童",
"group_size_min": 4,
"group_size_max": 4,
"use_dates_start": "2004-01-19",
"use_dates_end": "1990-03-10",
"weekdays": "4",
"audit_state": "ea pariatur",
"lastedit_memo": "sunt"
},
{
"id": "610000197306240177",
"value": 86,
"currency": "CNY",
"unit": "人",
"age_type": "儿童",
"group_size_min": 6,
"group_size_max": 8,
"use_dates_start": "1996-12-16",
"use_dates_end": "1974-11-19",
"weekdays": "4",
"audit_state": "aliqua aute quis ipsum",
"lastedit_memo": "commodo adipisicing ea ipsum"
}
],
"lgc_details": [
{
"lgc": "mollit",
"title": "林运但",
"description": "学克信图走法因心委周说步将且文手越。",
"id": "35"
},
{
"lgc": "et laborum",
"title": "备上引深量知量",
"description": "到听少文话包由北层中争二调原务越明在。",
"id": "74"
},
{
"lgc": "minim velit",
"title": "安都始新",
"description": "取影压前手府要青白支大而。",
"id": "23"
}
]
},
{
"info": {
"id": "41000019901227754X",
"title": "据划京少国取",
"code": "ore",
"type": "Guide",
"audit_state": "2",
"create_date": "1979-01-31",
"created_by": "陆芳",
"travel_agency_id": "110000198612200137",
"travel_agency_name": "少平酸型",
"lastedit_memo": "八想军也装运知长示各院步济水。",
"remarks": "千改原统实专回列参目党却是样与后收。",
"duration": 3,
"duration_unit": "d",
"open_weekdays": "5",
"recommends_rate": 5,
"dept": 1,
"display_to_c": "2",
"km": 30,
"city_id": 62,
"city_name": "业入"
},
"quotation": [
{
"id": "37000019760525515X",
"value": 93,
"currency": "CNY",
"unit": "团",
"age_type": "成人",
"group_size_min": 7,
"group_size_max": 11,
"use_dates_start": "1992-11-22",
"use_dates_end": "1997-07-16",
"weekdays": "7",
"audit_state": "id nulla irure cupidatat",
"lastedit_memo": "quis aute reprehenderit consectetur"
},
{
"id": "150000199506023175",
"value": 90,
"currency": "CNY",
"unit": "人",
"age_type": "儿童",
"group_size_min": 9,
"group_size_max": 10,
"use_dates_start": "2007-09-11",
"use_dates_end": "2013-07-27",
"weekdays": "5",
"audit_state": "commodo ad ut",
"lastedit_memo": "id anim incididunt"
}
],
"lgc_details": [
{
"lgc": "adipisicing elit Excepteur in",
"title": "很很结龙认",
"description": "事起复京长立然将采共层列工。",
"id": "43"
},
{
"lgc": "dolore fugiat",
"title": "专中小",
"description": "示史想当集认点离反而原化精满并计前。",
"id": "28"
},
{
"lgc": "sunt consectetur ea cillum",
"title": "他率带没",
"description": "节经厂面际是统表王活基书色活至是干验。",
"id": "83"
},
{
"lgc": "incididunt labore fugiat",
"title": "精话西改",
"description": "须事金性别民学少拉个且须专需断连。",
"id": "97"
},
{
"lgc": "dolore id",
"title": "文技话",
"description": "上任成条到则查支外很素给务府三。",
"id": "99"
}
]
},
{
"info": {
"id": "44000019990112280X",
"title": "节到和",
"code": "ixlmndtmz",
"type": "Meals",
"audit_state": "1",
"create_date": "2006-12-30",
"created_by": "易敏",
"travel_agency_id": "640000197111288408",
"travel_agency_name": "术备带走",
"lastedit_memo": "认队什教调问传改万消然声地全。",
"remarks": "属须厂几问总识看部群该克员方。",
"duration": 2,
"duration_unit": "m",
"open_weekdays": "6",
"recommends_rate": 3,
"dept": 2,
"display_to_c": "1",
"km": 13,
"city_id": 55,
"city_name": "铁以"
},
"quotation": [
{
"id": "13000019860219219X",
"value": 88,
"currency": "CNY",
"unit": "团",
"age_type": "儿童",
"group_size_min": 2,
"group_size_max": 4,
"use_dates_start": "1991-03-19",
"use_dates_end": "1974-03-13",
"weekdays": "3",
"audit_state": "officia voluptate ad adipisicing dolore",
"lastedit_memo": "Duis amet veniam enim"
},
{
"id": "420000201706118123",
"value": 61,
"currency": "CNY",
"unit": "人",
"age_type": "儿童",
"group_size_min": 4,
"group_size_max": 10,
"use_dates_start": "1992-04-23",
"use_dates_end": "1970-07-19",
"weekdays": "5",
"audit_state": "commodo labore",
"lastedit_memo": "ullamco anim culpa do in"
}
],
"lgc_details": [
{
"lgc": "ut minim",
"title": "回等这意",
"description": "农满界个整千书得被写况空派会想头无。",
"id": "40"
},
{
"lgc": "laborum id elit irure commodo",
"title": "增正数白养土子",
"description": "么划才共别程以元于族完难变。",
"id": "84"
}
]
}
], row => row.info.type),
}; };
export const useProductsStore = create( export const useProductsStore = create(
devtools((set, get) => ({ devtools((set, get) => ({
@ -287,6 +60,7 @@ export const useProductsStore = create(
// state actions // state actions
setLoading: loading => set({ loading }), setLoading: loading => set({ loading }),
setSearchValues: searchValues => set({ searchValues }),
setAgencyList: (agencyList) => set({ agencyList }), setAgencyList: (agencyList) => set({ agencyList }),
setActiveAgency: activeAgency => set({ activeAgency }), setActiveAgency: activeAgency => set({ activeAgency }),
setAgencyProducts: agencyProducts => set({ agencyProducts }), setAgencyProducts: agencyProducts => set({ agencyProducts }),

@ -7,15 +7,18 @@ import { useTranslation } from 'react-i18next';
import useProductsStore, { postProductsQuoteAudit } from '@/stores/Products/Index'; import useProductsStore, { postProductsQuoteAudit } from '@/stores/Products/Index';
import { isEmpty } from '@/utils/commons'; import { isEmpty } from '@/utils/commons';
const Header = ({ title, agency, ...props}) => { const Header = ({ title, agency, refresh, ...props}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [activeAgency, ] = useProductsStore((state) => [state.activeAgency]); const [activeAgency, ] = useProductsStore((state) => [state.activeAgency, ]);
const { message, notification } = App.useApp(); const { message, notification } = App.useApp();
const handleAuditItem = (state, row) => { const handleAuditItem = (state, row) => {
postProductsQuoteAudit(state, {id: row.id, travel_agency_id: activeAgency.travel_agency_id}) postProductsQuoteAudit(state, {id: row.id, travel_agency_id: activeAgency.travel_agency_id})
.then((json) => { .then((json) => {
if (json.errcode === 0) { if (json.errcode === 0) {
message.success('✔'); message.success(json.errmsg);
if (typeof refresh === 'function') {
refresh();
}
} }
}) })
.catch((ex) => { .catch((ex) => {
@ -34,8 +37,14 @@ const Header = ({ title, agency, ...props}) => {
</div> </div>
{/* <Button size='small'>{t('Copy')}</Button> */} {/* <Button size='small'>{t('Copy')}</Button> */}
{/* <Button size='small'>{t('Import')}</Button> */} {/* <Button size='small'>{t('Import')}</Button> */}
<Button size='small' type={'primary'} ghost onClick={() => handleAuditItem('2', agency)}> <Button size='small' type={'primary'} onClick={() => handleAuditItem('2', agency)}>
{t('products:auditStateAction.Published')}
</Button>
{/* <Button size='small' type={'primary'} ghost onClick={() => handleAuditItem('2', agency)}>
{t('products:auditStateAction.Approved')} {t('products:auditStateAction.Approved')}
</Button> */}
<Button size='small' type={'primary'} danger ghost onClick={() => handleAuditItem('3', agency)}>
{t('products:auditStateAction.Rejected')}
</Button> </Button>
{/* todo: export */} {/* todo: export */}
<Button size='small'>{t('Export')} PDF</Button> <Button size='small'>{t('Export')} PDF</Button>
@ -43,9 +52,9 @@ const Header = ({ title, agency, ...props}) => {
); );
}; };
const PriceTable = ({dataSource, loading}) => { const PriceTable = ({dataSource,refresh}) => {
const { t } = useTranslation('products'); const { t } = useTranslation('products');
const [activeAgency, ] = useProductsStore((state) => [state.activeAgency]); const [loading, activeAgency, ] = useProductsStore((state) => [state.loading, state.activeAgency, ]);
const { message, notification } = App.useApp(); const { message, notification } = App.useApp();
const stateMapVal = useProductsAuditStatesMapVal(); const stateMapVal = useProductsAuditStatesMapVal();
@ -53,7 +62,10 @@ const PriceTable = ({dataSource, loading}) => {
postProductsQuoteAudit(state, {id: row.id, travel_agency_id: activeAgency.travel_agency_id}) postProductsQuoteAudit(state, {id: row.id, travel_agency_id: activeAgency.travel_agency_id})
.then((json) => { .then((json) => {
if (json.errcode === 0) { if (json.errcode === 0) {
message.success('✔'); message.success(json.errmsg);
if (typeof refresh === 'function') {
refresh();
}
} }
}) })
.catch((ex) => { .catch((ex) => {
@ -68,11 +80,11 @@ const PriceTable = ({dataSource, loading}) => {
const columns = [ const columns = [
{ key: 'title', dataIndex: ['info', 'title'], title: t('Title'), onCell: (r, index) => ({ rowSpan: r.rowSpan }) }, { key: 'title', dataIndex: ['info', 'title'], title: t('Title'), onCell: (r, index) => ({ rowSpan: r.rowSpan }) },
{ key: 'value', title: t('Quotation'), render: (_, { value, currency, unit_name }) => `${value} ${currency} / ${unit_name}` }, { key: 'adult', title: t('AgeType.Adult'), render: (_, { value, currency, unit_name }) => `${value} ${currency} / ${unit_name}` },
{ key: 'child', title: t('AgeType.Child'), render: (_, { value, currency, unit_name }) => `${value} ${currency} / ${unit_name}` },
// {key: 'price', title: t('Currency'), }, // {key: 'price', title: t('Currency'), },
// {key: 'currency', title: t('Currency'), }, // {key: 'currency', title: t('Currency'), },
// {key: 'unit', title: t('Unit'), }, // {key: 'unit', title: t('Unit'), },
{ key: 'ageType', dataIndex: ['age_type'], title: t('AgeType.Type') },
{ {
key: 'groupSize', key: 'groupSize',
dataIndex: ['group_size_min'], dataIndex: ['group_size_min'],
@ -94,24 +106,24 @@ const PriceTable = ({dataSource, loading}) => {
}, },
}, },
{ {
title: '', title: '价格审核',
key: 'action', key: 'action',
render: (_, r) => r.audit_state_id <= 0 ?( render: (_, r) => r.audit_state_id <= 0 ?(
<Space> <Space>
<Button onClick={() => handleAuditPriceItem('2', r)}></Button> <Button onClick={() => handleAuditPriceItem('2', r)}></Button>
<Button onClick={() => handleAuditPriceItem('0', r)}></Button> <Button onClick={() => handleAuditPriceItem('3', r)}></Button>
</Space> </Space>
) : null, ) : null,
}, },
]; ];
return <Table pagination={false} columns={columns} dataSource={dataSource} rowKey={(r) => r.id} />; return <Table pagination={false} {...{ loading, columns, dataSource }} rowKey={(r) => r.id} />;
} }
/** /**
* *
*/ */
const TypesPanels = () => { const TypesPanels = (props) => {
const [loading, agencyProducts] = useProductsStore((state) => [state.loading, state.agencyProducts]); const [loading, agencyProducts, ] = useProductsStore((state) => [state.loading, state.agencyProducts]);
// console.log(agencyProducts); // console.log(agencyProducts);
const productsTypes = useProductsTypes(); const productsTypes = useProductsTypes();
const [activeKey, setActiveKey] = useState([]); const [activeKey, setActiveKey] = useState([]);
@ -125,8 +137,9 @@ const TypesPanels = () => {
...ele, ...ele,
children: ( children: (
<PriceTable <PriceTable
loading={loading} // loading={loading}
dataSource={agencyProducts[ele.value].reduce((r, c) => r.concat(c.quotation.map((q, i) => ({ ...q, info: c.info, rowSpan: i === 0 ? c.quotation.length : 0 }))), [])} dataSource={agencyProducts[ele.value].reduce((r, c) => r.concat(c.quotation.map((q, i) => ({ ...q, info: c.info, rowSpan: i === 0 ? c.quotation.length : 0 }))), [])}
refresh={props.refresh}
/> />
), ),
})); }));
@ -146,11 +159,11 @@ const TypesPanels = () => {
} }
const Audit = ({ ...props }) => { const Audit = ({ ...props }) => {
const { travel_agency_id } = useParams(); const { travel_agency_id, use_year, audit_state } = useParams();
const [activeAgency, getAgencyProducts] = useProductsStore((state) => [state.activeAgency, state.getAgencyProducts]); const [activeAgency, getAgencyProducts] = useProductsStore((state) => [state.activeAgency, state.getAgencyProducts]);
const handleGetAgencyProducts = () => { const handleGetAgencyProducts = () => {
getAgencyProducts({ travel_agency_id }); getAgencyProducts({ travel_agency_id, use_year, audit_state });
} }
useEffect(() => { useEffect(() => {
@ -161,9 +174,9 @@ const Audit = ({ ...props }) => {
return ( return (
<> <>
<SecondHeaderWrapper header={<Header title={activeAgency.travel_agency_name} agency={activeAgency} />}> <SecondHeaderWrapper header={<Header title={activeAgency.travel_agency_name} agency={activeAgency} refresh={handleGetAgencyProducts} />}>
<hr /> <hr />
<TypesPanels /> <TypesPanels refresh={handleGetAgencyProducts} />
</SecondHeaderWrapper> </SecondHeaderWrapper>
</> </>
); );

@ -11,16 +11,18 @@ import { objectMapper } from '@/utils/commons';
function Index() { function Index() {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, agencyList, searchAgency] = useProductsStore((state) => [state.loading, state.agencyList, state.searchAgency]); const [loading, agencyList, searchAgency] = useProductsStore((state) => [state.loading, state.agencyList, state.searchAgency]);
const [searchValues, setSearchValues] = useProductsStore((state) => [state.searchValues, state.setSearchValues]);
const formValuesToSub = useFormStore(state => state.formValuesToSub); const formValuesToSub = useFormStore(state => state.formValuesToSub);
const handleSearchAgency = (formVal = undefined) => { const handleSearchAgency = (formVal = undefined) => {
const { starttime, endtime, ...param } = formVal || formValuesToSub; const { starttime, endtime, ...param } = formVal || formValuesToSub;
const searchParam = objectMapper(param, { agency: 'travel_agency_id', startdate: 'edit_date1', enddate: 'edit_date2' }); const searchParam = objectMapper(param, { agency: 'travel_agency_id', startdate: 'edit_date1', enddate: 'edit_date2' });
setSearchValues(searchParam);
searchAgency(searchParam); searchAgency(searchParam);
} }
useEffect(() => { useEffect(() => {
handleSearchAgency(); // handleSearchAgency();
}, []); }, []);
const showTotal = (total) => t('Table.Total', { total }); const showTotal = (total) => t('Table.Total', { total });
@ -37,8 +39,8 @@ function Index() {
key: 'action', key: 'action',
render: (_, r) => ( render: (_, r) => (
<Space size={'large'}> <Space size={'large'}>
<Link to={`/products/${r.travel_agency_id}`}>{t('Edit')}</Link> <Link to={`/products/${r.travel_agency_id}/${searchValues.year || 'all'}/${searchValues.audit_state || 'all'}/edit`}>{t('Edit')}</Link>
<Link to={`/products/${r.travel_agency_id}/audit`}>{t('Audit')}</Link> <Link to={`/products/${r.travel_agency_id}/${searchValues.year || 'all'}/${searchValues.audit_state || 'all'}/audit`}>{t('Audit')}</Link>
</Space> </Space>
), ),
}, },
@ -47,19 +49,21 @@ function Index() {
<Space direction='vertical' style={{ width: '100%' }}> <Space direction='vertical' style={{ width: '100%' }}>
<SearchForm <SearchForm
fieldsConfig={{ fieldsConfig={{
shows: ['agency', 'audit_state', 'dates', 'keyword'], // todo: shows: ['agency', 'audit_state', 'dates', 'year', 'keyword'], // todo:
fieldProps: { fieldProps: {
agency: { col: 4 },
dates: { label: t('products:CreateDate') }, dates: { label: t('products:CreateDate') },
keyword: { label: t('products:Title')}, keyword: { label: t('products:Title'), col: 4 },
}, },
fieldComProps: { fieldComProps: {
agency: { mode: null }, // agency: { mode: null }, //
}, },
sort: { agency: 1, audit_state: 2, keyword: 100}, sort: { agency: 1, audit_state: 2, keyword: 100 },
}} }}
initialValue={{ initialValue={{
dates: [dayjs().subtract(2, 'M').startOf('M'), dayjs().endOf('M')], dates: [dayjs().subtract(2, 'M').startOf('M'), dayjs().endOf('M')],
audit_state: { value: '', label: t('products:State')}, audit_state: { value: '', label: t('products:State') },
year: dayjs().add(1, 'year'),
}} }}
onSubmit={(err, formVal, filedsVal) => { onSubmit={(err, formVal, filedsVal) => {
handleSearchAgency(formVal); handleSearchAgency(formVal);
@ -67,7 +71,14 @@ function Index() {
/> />
<Row> <Row>
<Col md={24} lg={24} xxl={24}> <Col md={24} lg={24} xxl={24}>
<Table bordered={true} columns={columns} dataSource={agencyList} pagination={{ defaultPageSize: 20, showTotal: showTotal }} loading={loading} rowKey={'travel_agency_id'} /> <Table
bordered={true}
columns={columns}
dataSource={agencyList}
pagination={{ defaultPageSize: 20, showTotal: showTotal }}
loading={loading}
rowKey={'travel_agency_id'}
/>
</Col> </Col>
<Col md={24} lg={24} xxl={24}></Col> <Col md={24} lg={24} xxl={24}></Col>
</Row> </Row>

Loading…
Cancel
Save