You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
17 KiB
JavaScript
485 lines
17 KiB
JavaScript
import { create } from 'zustand';
|
|
import { devtools } from 'zustand/middleware';
|
|
import dayjs from 'dayjs'
|
|
import { fetchJSON, postForm, postJSON } from '@/utils/request';
|
|
import { HT_HOST } from '@/config';
|
|
import { groupBy, generateId, isNotEmpty } from '@/utils/commons';
|
|
|
|
export const searchAgencyAction = async (param) => {
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/products_search`, param);
|
|
return errcode !== 0 ? [] : result;
|
|
};
|
|
|
|
/**
|
|
* 搜索所有产品, 返回产品列表
|
|
* ! 只有审核通过, 已发布的
|
|
* @param {object} params { keyword, use_year, product_types, travel_agency_id, city }
|
|
*/
|
|
export const searchPublishedProductsAction = async (param) => {
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/web_products_search`, param);
|
|
return errcode !== 0 ? [] : result;
|
|
};
|
|
|
|
export const copyAgencyDataAction = async (postbody) => {
|
|
const formData = new FormData();
|
|
Object.keys(postbody).forEach((key) => {
|
|
formData.append(key, postbody[key]);
|
|
});
|
|
const { errcode, result } = await postForm(`${HT_HOST}/Service_BaseInfoWeb/agency_products_copy`, formData);
|
|
return errcode === 0 ? true : false;
|
|
};
|
|
|
|
export const getAgencyProductsAction = async (param) => {
|
|
const _param = { ...param, use_year: String(param.use_year || '').replace('all', ''), audit_state: String(param.audit_state || '').replace('all', '') };
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/travel_agency_products`, _param);
|
|
return errcode !== 0 ? { agency: {}, products: [] } : result;
|
|
};
|
|
|
|
export const getAgencyAllExtrasAction = async (param) => {
|
|
const _param = { ...param, use_year: String(param.use_year || '').replace('all', ''), };
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_products_extras`, _param);
|
|
const extrasMapped = result.reduce((acc, curr) => ({...acc, [curr.product_id]: curr.extras}), {});
|
|
return errcode !== 0 ? {} : extrasMapped;
|
|
}
|
|
|
|
/**
|
|
* @param {object} body { id, travel_agency_id, extras: [{id, title, code}] }
|
|
*/
|
|
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;
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export const delProductExtrasAction = async (body) => {
|
|
// return true; // test: 先不更新到HT
|
|
const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/products_extras_del`, body);
|
|
return errcode === 0 ? true : false;
|
|
};
|
|
|
|
/**
|
|
* 获取指定产品的附加项目
|
|
* @param {object} param { id, travel_agency_id, use_year }
|
|
*/
|
|
export const getAgencyProductExtrasAction = async (param) => {
|
|
const _param = { ...param, use_year: String(param.use_year || '').replace('all', '') };
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/products_extras`, _param);
|
|
return errcode !== 0 ? [] : result;
|
|
};
|
|
|
|
/**
|
|
* 审核一条价格
|
|
*/
|
|
export const postProductsQuoteAuditAction = async (auditState, quoteRow) => {
|
|
const postbody = {
|
|
audit_state: auditState,
|
|
id: quoteRow.id,
|
|
travel_agency_id: quoteRow.travel_agency_id,
|
|
};
|
|
const formData = new FormData();
|
|
Object.keys(postbody).forEach((key) => {
|
|
formData.append(key, postbody[key]);
|
|
});
|
|
const json = await postForm(`${HT_HOST}/Service_BaseInfoWeb/quotation_audit`, formData);
|
|
return json;
|
|
// return errcode !== 0 ? {} : result;
|
|
};
|
|
|
|
export const postAgencyProductsAuditAction = async (auditState, agency) => {
|
|
const postbody = {
|
|
audit_state: auditState,
|
|
travel_agency_id: agency.travel_agency_id,
|
|
use_year: agency.use_year,
|
|
};
|
|
const formData = new FormData();
|
|
Object.keys(postbody).forEach((key) => {
|
|
formData.append(key, postbody[key]);
|
|
});
|
|
const json = await postForm(`${HT_HOST}/Service_BaseInfoWeb/agency_products_audit`, formData);
|
|
return json;
|
|
};
|
|
|
|
/**
|
|
* 供应商提交审核
|
|
*/
|
|
export const postAgencyAuditAction = async (travel_agency_id, use_year) => {
|
|
const postbody = {
|
|
use_year,
|
|
travel_agency_id,
|
|
};
|
|
const formData = new FormData();
|
|
Object.keys(postbody).forEach((key) => {
|
|
formData.append(key, postbody[key]);
|
|
});
|
|
const { errcode, result } = await postForm(`${HT_HOST}/Service_BaseInfoWeb/agency_submit`, formData);
|
|
return { errcode, result, success: errcode === 0 };
|
|
// const { errcode, result } = json;
|
|
// return errcode !== 0 ? {} : result;
|
|
};
|
|
|
|
/**
|
|
* 保存一个产品
|
|
*/
|
|
export const postProductsSaveAction = async (products) => {
|
|
const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_save`, products);
|
|
return { errcode, result, success: errcode === 0 };
|
|
}
|
|
|
|
/**
|
|
* 删除产品报价
|
|
*/
|
|
export const deleteQuotationAction = async (id) => {
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_quotation_delete`, {id});
|
|
return { errcode, result, success: errcode === 0 };
|
|
}
|
|
|
|
/**
|
|
* 获取合同备注
|
|
*/
|
|
export const fetchRemarkList = async (params) => {
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_memo_get`, params)
|
|
return { errcode, result, success: errcode === 0 }
|
|
}
|
|
|
|
/**
|
|
* 保存合同备注
|
|
*/
|
|
export const postRemarkList = async (params) => {
|
|
const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_memo_add`, params)
|
|
return { errcode, result, success: errcode === 0 }
|
|
}
|
|
|
|
/**
|
|
* 产品价格快照
|
|
*/
|
|
export const getPPSnapshotAction = async (params) => {
|
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_price_snapshot`, params)
|
|
return errcode !== 0 ? [] : result;
|
|
}
|
|
|
|
/**
|
|
* 产品价格日志
|
|
*/
|
|
export const getPPLogAction = async (params) => {
|
|
const { errcode, result } = await fetchJSON(`http://127.0.0.1:4523/m1/2602949-1933890-default/agency_product_price_log`, params)
|
|
return errcode !== 0 ? [] : result;
|
|
};
|
|
|
|
/**
|
|
* 产品价格: 已发布的
|
|
*/
|
|
export const getPPRunningAction = async (params) => {
|
|
const { errcode, result } = await fetchJSON(`http://127.0.0.1:4523/m1/2602949-1933890-default/agency_product_price_running`, params)
|
|
return errcode !== 0 ? [] : result;
|
|
};
|
|
|
|
/**
|
|
* 修改产品的类型
|
|
*/
|
|
export const moveProductTypeAction = async (params) => {
|
|
const { errcode, result } = await postJSON(`${HT_HOST}/Service_BaseInfoWeb/agency_product_move`, params)
|
|
return errcode !== 0 ? [] : result;
|
|
};
|
|
|
|
const defaultRemarkList = [
|
|
{id: 0, "product_type_id": "6","Memo": ""},
|
|
{id: 0, "product_type_id": "B","Memo": ""},
|
|
{id: 0, "product_type_id": "J","Memo": ""},
|
|
{id: 0, "product_type_id": "Q","Memo": ""},
|
|
{id: 0, "product_type_id": "7","Memo": ""},
|
|
{id: 0, "product_type_id": "R","Memo": ""},
|
|
{id: 0, "product_type_id": "D","Memo": ""}
|
|
]
|
|
|
|
const initialState = {
|
|
loading: false,
|
|
searchValues: {}, // 客服首页: 搜索条件
|
|
agencyList: [], // 客服首页: 搜索结果
|
|
activeAgency: {}, // 审核/编辑 页: 当前的供应商
|
|
activeAgencyState: null,
|
|
agencyProducts: {}, // 审核/编辑 页: 供应商产品列表
|
|
editingProduct: {}, // 编辑页: 当前编辑的产品
|
|
quotationList: [], // 编辑页: 当前产品报价列表
|
|
editing: false,
|
|
switchParams: {}, // 头部切换参数
|
|
}
|
|
|
|
export const useProductsStore = create(
|
|
devtools((set, get) => ({
|
|
// 初始化状态
|
|
...initialState,
|
|
|
|
// state actions
|
|
setLoading: (loading) => set({ loading }),
|
|
setSearchValues: (searchValues) => set({ searchValues }),
|
|
setAgencyList: (agencyList) => set({ agencyList }),
|
|
setActiveAgency: (activeAgency) => set({ activeAgency }),
|
|
setActiveAgencyState: (activeAgencyState) => set({ activeAgencyState }),
|
|
setAgencyProducts: (agencyProducts) => set({ agencyProducts }),
|
|
|
|
setEditingProduct: (product) => {
|
|
set(() => ({
|
|
editingProduct: product,
|
|
quotationList: (product?.quotation??[]).map(q => {
|
|
return {
|
|
...q,
|
|
key: generateId(),
|
|
fresh: false
|
|
}
|
|
})
|
|
}))
|
|
},
|
|
setEditing: (editing) => set({ editing }),
|
|
setSwitchParams: (switchParams) => set({ switchParams }),
|
|
|
|
appendNewProduct: (productItem) => {
|
|
const { setActiveAgency, agencyProducts, setAgencyProducts } = get();
|
|
const typeGroup = agencyProducts[productItem.info.product_type_id] || [];
|
|
const newIndex = typeGroup.findIndex((item) => item.info.id === productItem.info.id);
|
|
if (newIndex !== -1) {
|
|
typeGroup.splice(newIndex, 1, productItem);
|
|
} else {
|
|
typeGroup.unshift(productItem);
|
|
}
|
|
return set({
|
|
agencyProducts: { ...agencyProducts, [productItem.info.product_type_id]: typeGroup },
|
|
});
|
|
},
|
|
|
|
reset: () => set(initialState),
|
|
|
|
getRemarkList: async() => {
|
|
const {switchParams} = get()
|
|
const { result, success } = await fetchRemarkList({
|
|
travel_agency_id: switchParams.travel_agency_id, use_year: switchParams.use_year
|
|
})
|
|
if (success) {
|
|
const mapRemarkList = defaultRemarkList.map(remark => {
|
|
const filterResult = result.filter(r => r.product_type_id === remark.product_type_id)
|
|
if (filterResult.length > 0) return filterResult[0]
|
|
else return remark
|
|
})
|
|
|
|
return Promise.resolve(mapRemarkList)
|
|
} else {
|
|
return Promise.resolve('获取合同备注失败')
|
|
}
|
|
},
|
|
|
|
saveOrUpdateRemark: async(remarkList) => {
|
|
const {switchParams} = get()
|
|
|
|
const mapRemarkList = remarkList.map(remark => {
|
|
return {
|
|
id: remark.id,
|
|
travel_agency_id: switchParams.travel_agency_id,
|
|
use_year: switchParams.use_year,
|
|
product_type_id: remark.product_type_id,
|
|
Memo: remark.Memo,
|
|
}
|
|
})
|
|
|
|
const { result, success } = await postRemarkList(mapRemarkList)
|
|
if (success) {
|
|
return Promise.resolve(result)
|
|
} else {
|
|
return Promise.resolve('保存合同备注失败')
|
|
}
|
|
},
|
|
|
|
newEmptyQuotation: () => ({
|
|
id: null,
|
|
adult_cost: 0,
|
|
child_cost: 0,
|
|
currency: 'RMB',
|
|
unit_id: '0',
|
|
group_size_min: 1,
|
|
group_size_max: 10,
|
|
use_dates: [
|
|
dayjs().startOf('M'),
|
|
dayjs().endOf('M')
|
|
],
|
|
weekdayList: [],
|
|
fresh: true // 标识是否是新记录,新记录才用添加列表
|
|
}),
|
|
|
|
appendQuotationList: (defList) => {
|
|
const { activeAgency, editingProduct, quotationList } = get()
|
|
const generatedList = []
|
|
|
|
defList.forEach(definition => {
|
|
definition?.useDateList.map(useDateItem => {
|
|
const mappedPriceList = definition?.priceList.map(price => {
|
|
return {
|
|
id: null,
|
|
adult_cost: price.priceInput.audultPrice,
|
|
child_cost: price.priceInput.childrenPrice,
|
|
group_size_min: price.priceInput.numberStart,
|
|
group_size_max: price.priceInput.numberEnd,
|
|
|
|
currency: definition.currency,
|
|
unit_id: definition.unitId,
|
|
// 保持和 API 返回格式一致,日期要转换为字符串
|
|
use_dates_start: useDateItem.useDate[0].format('YYYY-MM-DD'),
|
|
use_dates_end: useDateItem.useDate[1].format('YYYY-MM-DD'),
|
|
weekdays: definition.weekend.join(','),
|
|
WPI_SN: editingProduct.info.id,
|
|
WPP_VEI_SN: activeAgency.travel_agency_id,
|
|
lastedit_changed: {},
|
|
audit_state_id: -1,
|
|
key: generateId(),
|
|
fresh: false
|
|
}
|
|
})
|
|
generatedList.push(...mappedPriceList)
|
|
})
|
|
})
|
|
|
|
const mergedList = [...quotationList,...generatedList]
|
|
set(() => ({
|
|
quotationList: mergedList
|
|
}))
|
|
|
|
return mergedList
|
|
},
|
|
|
|
saveOrUpdateQuotation: (formValues) => {
|
|
|
|
const { activeAgency, editingProduct, quotationList } = get()
|
|
let mergedList = []
|
|
|
|
formValues.WPI_SN = editingProduct.info.id
|
|
formValues.WPP_VEI_SN = activeAgency.travel_agency_id
|
|
formValues.use_dates_start = formValues.use_dates[0].format('YYYY-MM-DD')
|
|
formValues.use_dates_end = formValues.use_dates[1].format('YYYY-MM-DD')
|
|
formValues.weekdays = formValues.weekdayList.join(',')
|
|
|
|
if (formValues.fresh) {
|
|
formValues.key = generateId()
|
|
formValues.lastedit_changed = {}
|
|
formValues.audit_state_id = -1 // 新增,
|
|
formValues.fresh = false // 添加到列表后就不是新纪录,保存要修改原来记录
|
|
mergedList = [...quotationList,...[formValues]]
|
|
} else {
|
|
mergedList = quotationList.map(prevQuotation => {
|
|
if (prevQuotation.key === formValues.key) {
|
|
const changedObject = {}
|
|
for (const [key, value] of Object.entries(formValues)) {
|
|
if (key === 'use_dates' || key === 'id' || key === 'key' || key === 'weekdayList'
|
|
|| key === 'WPI_SN' || key === 'WPP_VEI_SN') continue
|
|
|
|
const preValue = prevQuotation[key]
|
|
const hasChanged = preValue !== value
|
|
|
|
if (hasChanged) {
|
|
changedObject[key] = value
|
|
}
|
|
}
|
|
|
|
return {
|
|
...prevQuotation,
|
|
audit_state_id: -1,
|
|
adult_cost: formValues.adult_cost,
|
|
child_cost: formValues.child_cost,
|
|
currency: formValues.currency,
|
|
unit_id: formValues.unit_id,
|
|
group_size_min: formValues.group_size_min,
|
|
group_size_max: formValues.group_size_max,
|
|
use_dates_start: formValues.use_dates_start,
|
|
use_dates_end: formValues.use_dates_end,
|
|
weekdays: formValues.weekdays,
|
|
lastedit_changed: changedObject
|
|
}
|
|
} else {
|
|
return prevQuotation
|
|
}
|
|
})
|
|
}
|
|
|
|
set(() => ({
|
|
quotationList: mergedList
|
|
}))
|
|
|
|
return mergedList
|
|
},
|
|
|
|
deleteQuotation: async(quotation) => {
|
|
const { editingProduct, quotationList, agencyProducts } = get()
|
|
const productTypeId = editingProduct.info.product_type_id;
|
|
const quotationId = quotation.id
|
|
const newQuotationList = quotationList.filter(q => {
|
|
return q.key != quotation.key
|
|
})
|
|
|
|
const newProductList = agencyProducts[productTypeId].map(p => {
|
|
if (p.info.id == editingProduct.info.id) {
|
|
return {
|
|
...editingProduct,
|
|
quotation: newQuotationList
|
|
}
|
|
} else {
|
|
return p
|
|
}
|
|
})
|
|
|
|
set({
|
|
agencyProducts: {
|
|
...agencyProducts,
|
|
[productTypeId]: newProductList
|
|
},
|
|
quotationList: newQuotationList
|
|
})
|
|
|
|
let promiseDelete = Promise.resolve(newQuotationList)
|
|
|
|
if (isNotEmpty(quotationId)) {
|
|
const { result, success } = await deleteQuotationAction(quotationId)
|
|
if (!success) {
|
|
promiseDelete = Promise.reject(result)
|
|
}
|
|
}
|
|
|
|
return promiseDelete
|
|
},
|
|
|
|
// side effects
|
|
searchAgency: async (param) => {
|
|
const { setLoading, setAgencyList } = get();
|
|
setLoading(true);
|
|
const res = await searchAgencyAction(param);
|
|
setAgencyList(res);
|
|
setLoading(false);
|
|
},
|
|
|
|
getAgencyProducts: async (param) => {
|
|
const { setLoading, setActiveAgency, setActiveAgencyState, setAgencyProducts, editingProduct, setEditingProduct } = get();
|
|
setLoading(true);
|
|
setAgencyProducts({});
|
|
// setEditingProduct({});
|
|
const res = await getAgencyProductsAction(param);
|
|
|
|
const productsData = groupBy(res.products, (row) => row.info.product_type_id);
|
|
setAgencyProducts(productsData);
|
|
setActiveAgency(res.agency);
|
|
setActiveAgencyState(res.agency.audit_state_id);
|
|
if (editingProduct?.info?.id) {
|
|
const item = (productsData[editingProduct.info.product_type_id] || []).find((item) => item.info.id === editingProduct.info.id);
|
|
setEditingProduct(item);
|
|
} else {
|
|
setEditingProduct({});
|
|
}
|
|
setLoading(false);
|
|
},
|
|
|
|
getAgencyProductExtras: async (param) => {
|
|
const res = await getAgencyProductExtrasAction(param);
|
|
// todo:
|
|
},
|
|
}), { name: 'productStore' })
|
|
);
|
|
export default useProductsStore;
|