多语种信息编辑

perf/export-docx
Lei OT 11 months ago
parent b2dcec8c37
commit f6b0dd8d04

@ -1,34 +1,25 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Form, Input, Row, Col, Select, DatePicker, Space, Button, InputNumber, Radio, Checkbox, Divider } from 'antd'; import { Form, Input, Row, Col, Select, Button, InputNumber, Checkbox } from 'antd';
import { objectMapper, at, isEmpty, isNotEmpty } from '@/utils/commons'; import { objectMapper, isEmpty, isNotEmpty } from '@/utils/commons';
import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from '@/config';
// import useFormStore from '@/stores/Form';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useWeekdays } from '@/hooks/useDatePresets'; import { useWeekdays } from '@/hooks/useDatePresets';
import DeptSelector from '@/components/DeptSelector'; import DeptSelector from '@/components/DeptSelector';
import CitySelector from '@/components/CitySelector'; import CitySelector from '@/components/CitySelector';
import { useProductsTypesFieldsets } from '@/hooks/useProductsSets';
import { fetchJSON } from '@/utils/request'; import useProductsStore from '@/stores/Products/Index';
import { HT_HOST } from '@/config';
// import SearchInput from './SearchInput';
// import AuditStateSelector from './AuditStateSelector';
import { useProductsTypesMapVal, useProductsTypesFieldsets } from '@/hooks/useProductsSets';
import useProductsStore, { postProductsSaveAction } from '@/stores/Products/Index';
import ProductInfoLgc from './ProductInfoLgc'; import ProductInfoLgc from './ProductInfoLgc';
import ProductInfoQuotation from './ProductInfoQuotation'; import ProductInfoQuotation from './ProductInfoQuotation';
import useAuthStore from '@/stores/Auth'; import useAuthStore from '@/stores/Auth';
import { PERM_PRODUCTS_MANAGEMENT, PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFER_PUT } from '@/config'; import { PERM_PRODUCTS_OFFER_AUDIT } from '@/config';
import { useHTLanguageSets, useHTLanguageSetsMapVal } from '@/hooks/useHTLanguageSets'; import { useHTLanguageSetsMapVal } from '@/hooks/useHTLanguageSets';
const { RangePicker } = DatePicker;
const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, showSubmit, confirmText, formName, ...props }) => { const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, showSubmit, confirmText, formName, ...props }) => {
const { t } = useTranslation('products'); const { t } = useTranslation('products');
const HTLanguageSetsMapVal = useHTLanguageSetsMapVal();
const isPermitted = useAuthStore((state) => state.isPermitted); const isPermitted = useAuthStore((state) => state.isPermitted);
const [loading, setLoading, agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.loading, state.setLoading, state.agencyProducts, state.editingProduct, state.setEditingProduct]); const [loading, editingProduct] = useProductsStore((state) => [state.loading, state.editingProduct]);
const weekdays = useWeekdays(); const weekdays = useWeekdays();
const HTLanguageSetsMapVal = useHTLanguageSetsMapVal();
const [form] = Form.useForm(); const [form] = Form.useForm();
const { sort, hides, fieldProps, fieldComProps } = { const { sort, hides, fieldProps, fieldComProps } = {
sort: '', sort: '',
@ -48,6 +39,7 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show
form.resetFields(); form.resetFields();
form.setFieldValue('city', { value: editingProduct?.info?.city_id, label: editingProduct?.info?.city_name }); form.setFieldValue('city', { value: editingProduct?.info?.city_id, label: editingProduct?.info?.city_name });
form.setFieldValue('dept', { value: editingProduct?.info?.dept_id, label: editingProduct?.info?.dept_name }); form.setFieldValue('dept', { value: editingProduct?.info?.dept_id, label: editingProduct?.info?.dept_name });
form.setFieldValue('lgc_details', editingProduct?.lgc_details || []);
const isNew = isEmpty(editingProduct?.info?.id) || _editable; // ; = const isNew = isEmpty(editingProduct?.info?.id) || _editable; // ; =
const ignoreEditable0 = topPerm || isNew; // const ignoreEditable0 = topPerm || isNew; //
@ -56,8 +48,7 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show
// console.log('+++++++++++++++++++', '\ntopPerm', topPerm, '\nisNew', isNew, '\nignoreEditable0', ignoreEditable0, '\neditable0', editable0, '\n_editable', _editable); // console.log('+++++++++++++++++++', '\ntopPerm', topPerm, '\nisNew', isNew, '\nignoreEditable0', ignoreEditable0, '\neditable0', editable0, '\n_editable', _editable);
setEditable(editable0); setEditable(editable0);
return () => {}; return () => {};
}, [editingProduct?.info?.id, _editable]) }, [editingProduct?.info?.id, _editable]);
const onFinish = (values) => { const onFinish = (values) => {
console.log('Received values of form, origin form value: \n', values); console.log('Received values of form, origin form value: \n', values);
@ -68,9 +59,9 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show
} }
}; };
const onFinishFailed = ({ values, errorFields, }) => { const onFinishFailed = ({ values, errorFields }) => {
console.log('form validate failed', '\nform values:', values, '\nerrorFields', errorFields); console.log('form validate failed', '\nform values:', values, '\nerrorFields', errorFields);
} };
const handleReset = () => { const handleReset = () => {
form.setFieldsValue({ form.setFieldsValue({
@ -82,19 +73,24 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show
}; };
const onIValuesChange = (changedValues, allValues) => { const onIValuesChange = (changedValues, allValues) => {
const dest = formValuesMapper(allValues); const dest = formValuesMapper(allValues);
// console.log('form onValuesChange', Object.keys(changedValues), args); // console.log('form onValuesChange', Object.keys(changedValues), changedValues);
if (typeof onValuesChange === 'function') { if (typeof onValuesChange === 'function') {
onValuesChange(dest); onValuesChange(dest);
} }
}; };
const onFieldsChange = (hangedFields, allFields) => {
console.log('onFieldsChange', hangedFields, allFields);
};
return ( return (
<> <>
<Form <Form
form={form} form={form}
disabled={!(editable || false)} disabled={!(editable || false)}
name={formName || 'product_info'} name={formName || 'product_info'}
// preserve={false}
onFinish={onFinish} onFinish={onFinish}
onValuesChange={onIValuesChange} onValuesChange={onIValuesChange}
// onFieldsChange={onFieldsChange}
initialValues={editingProduct?.info} initialValues={editingProduct?.info}
onFinishFailed={onFinishFailed}> onFinishFailed={onFinishFailed}>
<Row> <Row>
@ -110,16 +106,17 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show
)} */} )} */}
</Row> </Row>
{/* <Divider className='my-1' /> */} {/* <Divider className='my-1' /> */}
<Form.Item <Form.Item name={'lgc_details_mapped'}
name={'lgc_details'}
initialValue={[]}
rules={[ rules={[
() => ({ () => ({
transform(value) { transform(value) {
return value.filter(Boolean); return Object.values(value).filter(_v => !isEmpty(_v));
}, },
validator(_, value) { validator: async (_, valueArr) => {
const invalidLgcName = (value).filter(l => isEmpty(l.title)).map(x => HTLanguageSetsMapVal[x.lgc].label).join(', '); const invalidLgcName = valueArr
.filter((l) => isEmpty(l.title))
.map((x) => HTLanguageSetsMapVal[x.lgc].label)
.join(', ');
if (isNotEmpty(invalidLgcName)) { if (isNotEmpty(invalidLgcName)) {
return Promise.reject(new Error(`请完善多语种信息: ${invalidLgcName}`)); return Promise.reject(new Error(`请完善多语种信息: ${invalidLgcName}`));
} }
@ -159,7 +156,7 @@ function getFields(props) {
// const disabled = props.ignoreEditable ? false : (isEmpty(props.initialValue?.[name]) && props.editable ? false : true) // const disabled = props.ignoreEditable ? false : (isEmpty(props.initialValue?.[name]) && props.editable ? false : true)
const disabled = !props.editable; const disabled = !props.editable;
return { disabled, className: disabled ? '!text-slate-500' : '' }; return { disabled, className: disabled ? '!text-slate-500' : '' };
} };
const bigCol = 4 * 2; const bigCol = 4 * 2;
const midCol = 8; const midCol = 8;
const layoutProps = { const layoutProps = {
@ -178,7 +175,7 @@ function getFields(props) {
name, name,
render, render,
'hide': false, 'hide': false,
'col': { lg: { span: customCol }, md: { span: mdCol < 8 ? 10 : (mdCol > 24 ? 24 : mdCol) }, flex: mdCol < 8 ? '1 0' : '' }, 'col': { lg: { span: customCol }, md: { span: mdCol < 8 ? 10 : mdCol > 24 ? 24 : mdCol }, flex: mdCol < 8 ? '1 0' : '' },
}; };
}; };
let baseChildren = []; let baseChildren = [];
@ -186,7 +183,7 @@ function getFields(props) {
item( item(
'code', 'code',
99, 99,
<Form.Item name='code' label={t('Code')} {...fieldProps.code} rules={[{required: true}]}> <Form.Item name='code' label={t('Code')} {...fieldProps.code} rules={[{ required: true }]}>
<Input allowClear {...fieldComProps.code} {...styleProps} {...editableProps('code')} /> <Input allowClear {...fieldComProps.code} {...styleProps} {...editableProps('code')} />
</Form.Item>, </Form.Item>,
fieldProps?.code?.col || midCol fieldProps?.code?.col || midCol
@ -229,7 +226,9 @@ function getFields(props) {
99, 99,
<Form.Item name='recommends_rate' label={t('RecommendsRate')} {...fieldProps.recommends_rate}> <Form.Item name='recommends_rate' label={t('RecommendsRate')} {...fieldProps.recommends_rate}>
{/* <Input placeholder={t('RecommendsRate')} allowClear /> */} {/* <Input placeholder={t('RecommendsRate')} allowClear /> */}
<Select {...styleProps} {...editableProps('recommends_rate')} <Select
{...styleProps}
{...editableProps('recommends_rate')}
style={{ width: '100%' }} style={{ width: '100%' }}
labelInValue={false} labelInValue={false}
options={[ options={[
@ -267,11 +266,16 @@ function getFields(props) {
{ value: 153002, label: '计划不显示' }, { value: 153002, label: '计划不显示' },
]} ]}
/> */} /> */}
<Select labelInValue={false} options={[ <Select
labelInValue={false}
options={[
{ value: '153001', label: '在计划显示,不在报价信显示' }, { value: '153001', label: '在计划显示,不在报价信显示' },
{ value: 0, label: '计划和报价信都要显示' }, { value: 0, label: '计划和报价信都要显示' },
{ value: '153001, 153002', label: '计划和报价信都不用显示' }, { value: '153001, 153002', label: '计划和报价信都不用显示' },
]} {...styleProps} {...editableProps('display_to_c')} /> ]}
{...styleProps}
{...editableProps('display_to_c')}
/>
</Form.Item>, </Form.Item>,
fieldProps?.display_to_c?.col || midCol fieldProps?.display_to_c?.col || midCol
), ),
@ -342,25 +346,34 @@ function getFields(props) {
const formValuesMapper = (values) => { const formValuesMapper = (values) => {
const destinationObject = { const destinationObject = {
'city': [{ key: 'city_id', transform: (value) => value?.value || value?.key || '' }, { key: 'city_name', transform: (value) => value?.label || '' }], 'city': [
'dept': { key: 'dept', transform: (value) => typeof value === 'string' ? value : (value?.value || value?.key || '') }, { key: 'city_id', transform: (value) => value?.value || value?.key || '' },
{ key: 'city_name', transform: (value) => value?.label || '' },
],
'dept': { key: 'dept', transform: (value) => (typeof value === 'string' ? value : value?.value || value?.key || '') },
'open_weekdays': { key: 'open_weekdays', transform: (value) => (Array.isArray(value) ? value.join(',') : value) }, 'open_weekdays': { key: 'open_weekdays', transform: (value) => (Array.isArray(value) ? value.join(',') : value) },
'recommends_rate': { key: 'recommends_rate', transform: (value) => typeof value === 'string' ? value : (value?.value || value?.key || '') }, 'recommends_rate': { key: 'recommends_rate', transform: (value) => (typeof value === 'string' ? value : value?.value || value?.key || '') },
'lgc_details': [ // 'lgc_details': [
{ // {
key: 'lgc_details', // key: 'lgc_details',
transform: (value) => { // transform: (value) => {
const _val = value.filter((s) => s !== undefined).map((e) => ({ title: '', ...e, description: e.description || '' })); // const _val = value.filter((s) => s !== undefined).map((e) => ({ title: '', ...e, description: e.description || '' }));
return _val || ''; // return _val || '';
}, // },
}, // },
{ // {
key: 'lgc_details_mapped', // key: 'lgc_details_mapped_tmp',
transform: (value) => { // transform: (value) => {
const _val = value.filter((s) => s !== undefined); // const _val = value.filter((s) => s !== undefined);
return _val.reduce((r, c) => ({ ...r, [c.lgc]: c }), {}); // return _val.reduce((r, c) => ({ ...r, [c.lgc]: c }), {});
}, // },
}, // },
// ],
'lgc_details_mapped': [
{ key: 'lgc_details', transform: (value) => {
const valueArr = Object.values(value).filter(_v => !isEmpty(_v));
return valueArr;
}},
], ],
}; };
let dest = {}; let dest = {};
@ -377,5 +390,4 @@ const formValuesMapper = (values) => {
return { info, lgc_details, lgc_details_mapped, quotation }; return { info, lgc_details, lgc_details_mapped, quotation };
}; };
export default InfoForm; export default InfoForm;

@ -1,17 +1,17 @@
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState } from 'react';
import { Input, Tabs, Modal, Select, Form } from 'antd'; import { Input, Tabs, Modal, Select, Form } from 'antd';
import useProductsStore from '@/stores/Products/Index'; import useProductsStore from '@/stores/Products/Index';
import { useHTLanguageSets, useHTLanguageSetsMapVal } from '@/hooks/useHTLanguageSets'; import { useHTLanguageSets, useHTLanguageSetsMapVal } from '@/hooks/useHTLanguageSets';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDefaultLgc } from '@/i18n/LanguageSwitcher'; import { useDefaultLgc } from '@/i18n/LanguageSwitcher';
import { isEmpty } from '@/utils/commons'; import { cloneDeep, isEmpty, isNotEmpty } from '@/utils/commons';
const ProductInfoLgc = ({ editable, ignoreEditable, formInstance, ...props }) => { const ProductInfoLgc = ({ editable, ignoreEditable, formInstance, ...props }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { language: languageHT } = useDefaultLgc(); const { language: languageHT } = useDefaultLgc();
const HTLanguageSetsMapVal = useHTLanguageSetsMapVal(); const HTLanguageSetsMapVal = useHTLanguageSetsMapVal();
const allLgcOptions = useHTLanguageSets(); const allLgcOptions = useHTLanguageSets();
const [ editingProduct, ] = useProductsStore((state) => [ state.editingProduct, ]); const [editingProduct] = useProductsStore((state) => [state.editingProduct]);
const [activeKey, setActiveKey] = useState(); const [activeKey, setActiveKey] = useState();
const [items, setItems] = useState([]); const [items, setItems] = useState([]);
@ -19,35 +19,41 @@ const ProductInfoLgc = ({ editable, ignoreEditable, formInstance, ...props }) =>
const existsLgc = (editingProduct?.lgc_details || []).map((ele, li) => ({ const existsLgc = (editingProduct?.lgc_details || []).map((ele, li) => ({
...ele, ...ele,
label: HTLanguageSetsMapVal[ele.lgc].label, label: HTLanguageSetsMapVal[ele.lgc].label,
key: `${editingProduct.info.id}-${ele.id}`, // key: `${editingProduct.info.id}-${ele.id}`,
key: ele.lgc,
closable: false, // isPermitted(PERM_PRODUCTS_MANAGEMENT) ? true : false, closable: false, // isPermitted(PERM_PRODUCTS_MANAGEMENT) ? true : false,
forceRender: true,
children: ( children: (
<> <Form.Item>
<Form.Item name={[li, 'title']} label={t('products:Title')} initialValue={ele.title}> <Form.Item name={['lgc_details_mapped', `${ele.lgc}`, 'title']} label={t('products:Title')} initialValue={ele.title} rules={[{ required: true }]}>
<Input className={' !text-slate-600'} allowClear <Input
className={' !text-slate-600'}
allowClear
// onChange={(e) => handleChange('title', e.target.value)} // onChange={(e) => handleChange('title', e.target.value)}
// disabled={isCanEditable} // disabled={isCanEditable}
// disabled={ignoreEditable ? false : (!isEmpty(ele.title) || !editable)} // disabled={ignoreEditable ? false : (!isEmpty(ele.title) || !editable)}
disabled={ignoreEditable ? false : (!editable)} disabled={ignoreEditable ? false : !editable}
// disabled={!editable} // disabled={!editable}
/> />
</Form.Item> </Form.Item>
<Form.Item name={[li, 'description']} label={t('products:Description')} initialValue={ele.descriptions}> <Form.Item name={['lgc_details_mapped', `${ele.lgc}`, 'description']} label={t('products:Description')} initialValue={ele.descriptions}>
<Input.TextArea className={'!text-slate-600'} <Input.TextArea
rows={3} allowClear className={'!text-slate-600'}
rows={3}
allowClear
// onChange={(e) => handleChange('description', e.target.value)} // onChange={(e) => handleChange('description', e.target.value)}
// disabled={ignoreEditable ? false : (!isEmpty(ele.descriptions) || !editable)} // disabled={ignoreEditable ? false : (!isEmpty(ele.descriptions) || !editable)}
disabled={ignoreEditable ? false : (!editable)} disabled={ignoreEditable ? false : !editable}
// disabled={!editable} // disabled={!editable}
/> />
</Form.Item> </Form.Item>
<Form.Item hidden name={[li, 'lgc']} initialValue={ele.lgc}> <Form.Item hidden name={['lgc_details_mapped', `${ele.lgc}`, 'lgc']} initialValue={ele.lgc}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item hidden name={[li, 'id']} initialValue={ele.id}> <Form.Item hidden name={['lgc_details_mapped', `${ele.lgc}`, 'id']} initialValue={ele.id}>
<Input /> <Input />
</Form.Item> </Form.Item>
</> </Form.Item>
), ),
})); }));
setItems(existsLgc); setItems(existsLgc);
@ -60,37 +66,44 @@ const ProductInfoLgc = ({ editable, ignoreEditable, formInstance, ...props }) =>
return () => {}; return () => {};
}, [editingProduct]); }, [editingProduct]);
const onChange = (newActiveKey) => { const onLgcTabChange = (newActiveKey) => {
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
}; };
const addLgc = (lgcItem) => { const addLgc = (lgcItem) => {
const newActiveKey = lgcItem.value; // `newTab${newTabIndex.current++}`; // const currentLgcOptions = structuredClone(lgcOptions);
const i = 8+Number(lgcItem.value); const currentLgcOptions = cloneDeep(lgcOptions);
currentLgcOptions.splice(
currentLgcOptions.findIndex((ele) => ele.value === lgcItem.value),
1
);
setLgcOptions(currentLgcOptions);
const newActiveKey = lgcItem.value;
const newPanes = [...items]; const newPanes = [...items];
newPanes.push({ newPanes.push({
...lgcItem, ...lgcItem,
forceRender: true,
key: lgcItem.value,
children: ( children: (
<> <Form.Item>
<Form.Item name={[i, 'title']} label={t('products:Title')} initialValue={''} rules={[{required: true}]}> <Form.Item name={['lgc_details_mapped', `${lgcItem.value}`, 'title']} preserve={false} label={t('products:Title')} rules={[{ required: true }]}>
<Input /> <Input allowClear />
</Form.Item> </Form.Item>
<Form.Item name={[i, 'description']} label={t('products:Description')} initialValue={''}> <Form.Item name={['lgc_details_mapped', `${lgcItem.value}`, 'description']} preserve={false} label={t('products:Description')}>
<Input.TextArea rows={3} /> <Input.TextArea rows={3} allowClear />
</Form.Item> </Form.Item>
<Form.Item hidden name={[i, 'lgc']} initialValue={lgcItem.value}> <Form.Item hidden name={['lgc_details_mapped', `${lgcItem.value}`, 'lgc']} preserve={false} initialValue={lgcItem.value}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item hidden name={[i, 'id']} initialValue={''}> <Form.Item hidden name={['lgc_details_mapped', `${lgcItem.value}`, 'id']} preserve={false} initialValue={''}>
<Input /> <Input />
</Form.Item> </Form.Item>
</> </Form.Item>
), ),
}); });
setItems(newPanes); setItems(newPanes);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
const currentLgcOptions = structuredClone(lgcOptions);
currentLgcOptions.splice(currentLgcOptions.findIndex(ele => ele.value === lgcItem.value), 1);
setLgcOptions(currentLgcOptions);
setSelectNewLgc(null); setSelectNewLgc(null);
}; };
const remove = (targetKey) => { const remove = (targetKey) => {
@ -111,7 +124,7 @@ const ProductInfoLgc = ({ editable, ignoreEditable, formInstance, ...props }) =>
} }
setItems(newPanes); setItems(newPanes);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
setLgcOptions([...lgcOptions, ...items.filter(item => item.key === targetKey)]); setLgcOptions([...lgcOptions, ...items.filter((item) => item.key === targetKey)]);
}; };
const onEdit = (targetKey, action) => { const onEdit = (targetKey, action) => {
if (action === 'add') { if (action === 'add') {
@ -136,10 +149,17 @@ const ProductInfoLgc = ({ editable, ignoreEditable, formInstance, ...props }) =>
}; };
return ( return (
<> <>
<Form.List name={'lgc_details'}> <Tabs
{(fields, { add, remove }) => <Tabs type='editable-card' size='small' onChange={onChange} activeKey={activeKey} onEdit={onEdit} items={items} hideAdd={isEmpty(lgcOptions) || !editable} tabPosition='top' />} type='editable-card'
</Form.List> size='small'
<Modal title='选择语言' open={newLgcModalVisible} onOk={handleOk} onCancel={() => setNewLgcModalVisible(false)}> onChange={onLgcTabChange}
activeKey={activeKey}
onEdit={onEdit}
items={items}
hideAdd={isEmpty(lgcOptions) || !editable}
tabPosition='top'
/>
<Modal title={'选择语言'} open={newLgcModalVisible} onOk={handleOk} onCancel={() => setNewLgcModalVisible(false)}>
<Select <Select
showSearch showSearch
labelInValue labelInValue

Loading…
Cancel
Save