Commit 8ebe9dd6 authored by 武广's avatar 武广

Merge branch 'feature/new-goods-up' into 'master'

Feature/new goods up

See merge request !68
parents 63018594 7f8a5003
const isProduction = process.env.NODE_ENV === 'production';
const isPre = process.env.PRE_ENV === 'pre';
const environment = 'yxm2';
const environment = 'xyqb';
const envAPi = {
api: `https://security-${environment}.liangkebang.net`, //'https://security-xyqb.liangkebang.net',
kdspOpApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
kdspApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
goodsApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
querysApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
querysApi: `https://sc-merchant-api-${environment}.liangkebang.net/admin/merchant/sc-settlement`,
prologueDomain: `https://mall-${environment}.liangkebang.net`,
qiniuHost: 'https://kdspstatic.q-gp.com/',
opapiHost: `https://opapi-${environment}.liangkebang.net`,
opapiHost: `https://gw.yxmie.com`,
wsApi: `wss://push-${environment}.liangkebang.net`,
msgApi: `https://msgapi-${environment}.liangkebang.net`,
};
......
import React, { useEffect, useRef, useState } from 'react';
import { Select, Space, Divider, Input, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import styles from './index.less';
const CustomSelect = props => {
const [name, setName] = useState('');
const [items, setItems] = useState([]);
const inputRef = useRef(null);
const onNameChange = e => {
setName(e.target.value);
};
const addItem = e => {
e.preventDefault();
const v = name.trim();
if (v) {
setItems([...items, { name: v }]);
setName('');
setTimeout(() => {
// eslint-disable-next-line no-unused-expressions
inputRef.current?.focus();
}, 0);
}
};
const onChange = e => {
props.onChange(e);
};
useEffect(() => {
setItems(props.options);
}, [props.options]);
return (
<Select
mode={props.mode}
maxTagTextLength={8}
allowClear
value={props.value}
onChange={onChange}
dropdownRender={menu => (
<>
{menu}
{props.isCustom && (
<>
<Divider className={styles.SelectDivider} />
<Space className={styles.SelectSpace}>
<Input
className={styles.SelectInput}
placeholder="请输入自定义属性"
ref={inputRef}
value={name}
maxLength={30}
onChange={onNameChange}
/>
<Button type="primary" icon={<PlusOutlined />} onClick={addItem} />
</Space>
</>
)}
</>
)}
options={items.map(item => ({ label: item.name, value: JSON.stringify(item) }))}
></Select>
);
};
export default CustomSelect;
.SelectDivider {
margin: 8px 0;
}
.SelectSpace {
width: 100%;
padding: 0 8px 4px;
:global {
.ant-space-item:first-child {
width: 100%;
}
}
}
.SelectInput {
width: 100%;
}
......@@ -98,6 +98,7 @@ const Complex = props => {
setLoading(true);
const res = await apiGetBussinessMsgList(data, params);
setLoading(false);
if (!res) return;
if (res.code !== '0000') {
notification.error(res.msg);
return;
......
......@@ -149,6 +149,7 @@ const Simple = props => {
setLoading(true);
const res = await apiGetBussinessMsgList(data, params);
setLoading(false);
if (!res) return;
if (res.code !== '0000') {
notification.error(res.msg);
return;
......
/* eslint-disable no-param-reassign */
import { Form, Select, Input, InputNumber, Button } from 'antd';
import React, { Component } from 'react';
// import styles from '../style.less';
const { Option } = Select;
const FormItem = Form.Item;
class goodsManage extends Component {
formRef = React.createRef();
componentDidMount() {
this.props.onRef(this);
}
setFiled = flag => {
const form = this.formRef.current;
if (flag === 'firstKeys') {
form.setFieldsValue({ firstSpecValue: '' });
return;
}
form.setFieldsValue({ secondSpecValue: '' });
};
batchSetting = () => {
const { editData, isEdit } = this.props;
const form = this.formRef.current;
const data = form.getFieldsValue();
if (!data.firstSpecValue && !data.secondSpecValue) {
editData.forEach(item => {
item.marketPrice = data.marketPrice;
// if (!isEdit) item.productStock = data.productStock; // 编辑状态不可修改库存
item.productStock = data.productStock;
item.supplyPrice = data.supplyPrice;
item.weight = data.weight;
item.productStockWarning = data.productStockWarning;
});
}
if (data.firstSpecValue && !data.secondSpecValue) {
editData.forEach(item => {
if (item.firstSpecValue === data.firstSpecValue) {
item.marketPrice = data.marketPrice;
item.productStock = data.productStock;
item.supplyPrice = data.supplyPrice;
item.weight = data.weight;
item.productStockWarning = data.productStockWarning;
}
});
}
if (!data.firstSpecValue && data.secondSpecValue) {
editData.forEach(item => {
if (item.secondSpecValue === data.secondSpecValue) {
item.marketPrice = data.marketPrice;
item.productStock = data.productStock;
item.supplyPrice = data.supplyPrice;
item.weight = data.weight;
item.productStockWarning = data.productStockWarning;
}
});
}
if (data.firstSpecValue && data.secondSpecValue) {
editData.forEach(item => {
if (
item.firstSpecValue === data.firstSpecValue &&
item.secondSpecValue === data.secondSpecValue
) {
item.marketPrice = data.marketPrice;
item.productStock = data.productStock;
item.supplyPrice = data.supplyPrice;
item.weight = data.weight;
item.productStockWarning = data.productStockWarning;
}
});
}
this.props.batchSetting(editData);
};
render() {
const {
firstSpes = [],
secondSpecs = [],
firstSpesName = '',
secondSpesName = '',
productType,
isEdit,
isService,
} = this.props;
return (
<Form layout="inline" ref={this.formRef}>
<FormItem name="firstSpecValue">
<Select allowClear style={{ width: 120 }} placeholder={firstSpesName}>
{firstSpes.length > 0 &&
firstSpes.map(
item =>
item &&
typeof item === 'string' && (
<Option key={item} value={item}>
{item}
</Option>
),
)}
</Select>
</FormItem>
<FormItem name="secondSpecValue">
<Select allowClear style={{ width: 120 }} placeholder={secondSpesName}>
{secondSpecs.length &&
secondSpecs.map(
item =>
item &&
typeof item === 'string' && (
<Option key={item} value={item}>
{item}
</Option>
),
)}
</Select>
</FormItem>
<FormItem name="supplyPrice">
<Input placeholder="供货价" style={{ width: 100 }} />
</FormItem>
<FormItem name="marketPrice">
<Input placeholder="市场价" style={{ width: 100 }} />
</FormItem>
{/* <FormItem>
{getFieldDecorator('salePrice', {})(
<Input placeholder="销售价" style={{ width: 100 }} />,
)}
</FormItem> */}
{productType === 1 && (
<FormItem name="weight">
<InputNumber
precision={3}
max={999999.999}
// eslint-disable-next-line radix
placeholder="重量"
style={{ width: 130 }}
/>
</FormItem>
)}
<FormItem name="productStock">
<InputNumber
precision={0}
step={1}
// eslint-disable-next-line radix
formatter={val => parseInt(val, '10') || ''}
placeholder="库存"
style={{ width: 100 }}
/>
</FormItem>
{productType === 1 && (
<FormItem name="productStockWarning">
<InputNumber
placeholder="库存预警"
maxLength={5}
min={0}
precision={0}
style={{ width: 100 }}
/>
</FormItem>
)}
<FormItem>
<Button type="primary" htmlType="submit" onClick={this.batchSetting} disabled={isService}>
批量设置
</Button>
</FormItem>
</Form>
);
}
}
export default goodsManage;
import { Row, Col, Button } from 'antd';
import React, { Component } from 'react';
import styles from '../style.less';
// eslint-disable-next-line react/prefer-stateless-function
class ButtonGroup extends Component {
render() {
const { initData, confirmLoading } = this.props;
return (
<Row type="flex" justify="center" align="middle" gutter={20}>
<Col>
<Button type="primary" onClick={() => this.props.onCancel()} className={styles.logBtn}>
取消
</Button>
</Col>
<Col key="submit">
<Button
type="primary"
onClick={() => this.props.confirm()}
className={styles.logBtn}
loading={confirmLoading}
disabled={confirmLoading}
>
提交
</Button>
</Col>
{initData && !Object.keys(initData).length && (
<Col key="submit-add">
<Button
type="primary"
onClick={() => this.props.confirm(true)}
className={styles.logBtn}
loading={confirmLoading}
disabled={confirmLoading}
>
提交并继续添加
</Button>
</Col>
)}
</Row>
);
}
}
export default ButtonGroup;
This diff is collapsed.
This diff is collapsed.
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import { Input, Modal } from 'antd';
import React, { Component } from 'react';
const { TextArea } = Input;
const FormItem = Form.Item;
// import styles from '../style.less';
class goodsManage extends Component {
// componentDidMount() {
// this.props.onRef(this);
// }
handleOk = () => {
const { form } = this.props;
form.validateFields((err, values) => {
if (!err) {
this.props.changeSkuName(values.name);
this.props.form.resetFields();
}
});
};
handleCancel = () => {
this.props.form.resetFields();
this.props.onCancle();
};
render() {
const { data, visible, form } = this.props;
const { getFieldDecorator } = form;
return (
<Modal title="" visible={visible} onOk={this.handleOk} onCancel={this.handleCancel}>
<Form>
<FormItem label="sku名称">
{getFieldDecorator('name', {
initialValue: data,
rules: [
{
required: true,
message: '请输入',
},
],
})(<TextArea autoSize={{ minRows: 2, maxRows: 6 }} allowClear />)}
</FormItem>
</Form>
</Modal>
);
}
}
export default Form.create()(goodsManage);
......@@ -4,7 +4,6 @@ import { Card, Pagination, Table, notification, Drawer, Spin, Button, Modal } fr
import React, { Component } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva';
import { sortBy } from 'lodash';
import styles from './style.less';
import LocalStroage from '@/utils/localStorage';
import configApi from '../../../config/env.config';
......@@ -21,12 +20,11 @@ import {
apiQueryLastChangeLog,
} from './service';
import LogModal from './LogModal';
import CreateModal from './createModal';
import { column, JDSHOPID, ProcessEditData } from './staticdata';
import SearchForm from './SearchForm';
import TempleatModal from './TempleatModal';
import ServiceGoods from '../ServiceGoods';
import InfoAudit from './createModal/infoAudit';
import InfoAudit from './infoAudit';
import { GOOD_MANAGE } from '@/../config/permission.config';
......@@ -44,9 +42,7 @@ class goodsManage extends Component {
priceInfo: {},
logVisible: false,
previewVisible: false,
createVisible: false, // 新增or编辑普通商品modal
updateStockVisible: false,
initData: {},
createloading: false,
specListData: [],
templeatModalVisible: false,
......@@ -126,64 +122,6 @@ class goodsManage extends Component {
this.handleSearch();
};
onUpdateInfo = async ({ state, spuId, productType }) => {
this.setState({
createloading: true,
});
const { data, msg } = await spuDetail({ id: spuId }); // spuId
if (data) {
data.state = state;
data.pageProductType = productType;
data.categoryId = data.thirdCategoryId;
data.firstSpecId = data.skuList[0].firstSpecId;
data.secondSpecId = data.skuList[0].secondSpecId;
data.firstSpecName = data.skuList[0].firstSpec;
data.secondSpecName = data.skuList[0].secondSpec;
data.firstSpecList = [];
data.secondSpecList = [];
data.colorKeys = [];
data.carouseList.forEach(i => {
if (i.specValue) {
data.colorKeys.push(i.specValue);
}
});
data.skuList.forEach(i => {
if (data.firstSpecList.indexOf(i.firstSpecValue) === -1) {
data.firstSpecList.push(`${i.firstSpecValue}`);
}
if (i.secondSpecValue && data.secondSpecList.indexOf(i.secondSpecValue) === -1) {
data.secondSpecList.push(i.secondSpecValue);
}
});
data.specs.forEach(item => {
const arr = [];
if (item.specValues.length) {
item.specValues.forEach(childItem => {
arr.push(childItem.value);
});
}
data[item.specId] = arr;
});
data.imageList = [];
data.carouseList.forEach(i => {
data.imageList[`${i.specValue}`] = i.skuSpecImageList || [];
});
data.editData = sortBy(data.skuList, item => item.firstSpecValue);
this.setState({
initData: data,
createVisible: true,
createloading: false,
});
} else {
this.setState({
createloading: false,
});
notification.warning({
message: msg,
});
}
};
onLoad = error => {
if (!error) {
notification.success({ message: '操作成功' });
......@@ -389,6 +327,11 @@ class goodsManage extends Component {
}
};
onEdit = () => {
this.setState({ visibleAuditModal: false, auditRow: {} });
this.serviceVisbleChange(this.state.auditRow);
};
render() {
const {
goodsManage: { tableData = {} },
......@@ -405,30 +348,18 @@ class goodsManage extends Component {
this.canEditable = permissions[GOOD_MANAGE.EDITABLE];
return (
<PageHeaderWrapper>
{canAddNormal || canAddService ? (
<Button
type="primary"
className={styles.button}
onClick={() => this.serviceVisbleClose(true)}
>
新增商品
</Button>
) : (
''
)}
<Spin spinning={this.state.createloading}>
{canAddNormal ? (
<Button
type="primary"
className={styles.button}
onClick={() => this.setState({ createVisible: true, initData: {} })}
>
新增商品
</Button>
) : (
''
)}
{canAddService ? (
<Button
type="primary"
className={styles.button}
onClick={() => this.serviceVisbleClose(true)}
>
新增服务类商品
</Button>
) : (
''
)}
<Card>
<SearchForm
handleSearch={this.handleSearch}
......@@ -440,7 +371,6 @@ class goodsManage extends Component {
treeData={this.state.treeData}
shopList={this.shopList}
checkStock={this.checkEnableUpdateStock}
// addSpu={() => this.setState({ createVisible: true, initData: {} })}
selectNum={selectedRowKeys.length}
setArea={(isALL, type) => this.setArea(isALL, type)}
/>
......@@ -497,20 +427,6 @@ class goodsManage extends Component {
title="商品预览"
></iframe>
</Drawer>
{this.state.createVisible && (
<CreateModal
initData={this.state.initData}
visible={this.state.createVisible}
onCancel={() => {
this.setState({ createVisible: false, initData: {} });
}}
query={() => this.handleSearch()}
shopList={this.filterShopList(this.shopList, Object.keys(this.state.initData).length)}
treeData={this.state.treeData}
virtualTreeData={this.state.virtualTreeData}
specListData={this.state.specListData}
></CreateModal>
)}
<UpdateStock
visible={this.state.updateStockVisible}
......@@ -530,33 +446,30 @@ class goodsManage extends Component {
isType={this.state.isType}
templateList={this.state.templateList}
/>
{/* '894048258062' */}
<ServiceGoods
visible={this.state.serviceVisble}
onChange={this.serviceVisbleClose}
SourceData={this.state.serviceData}
shopList={this.shopList}
categoryList={this.state.treeData}
virtualCategoryList={this.state.virtualTreeData}
specListData={this.state.specListData}
/>
{this.state.serviceVisble && (
<ServiceGoods
visible={this.state.serviceVisble}
onChange={this.serviceVisbleClose}
SourceData={this.state.serviceData}
shopList={this.shopList}
categoryList={this.state.treeData}
virtualCategoryList={this.state.virtualTreeData}
specListData={this.state.specListData}
permissions={permissions}
/>
)}
</Spin>
<InfoAudit
visible={this.state.visibleAuditModal}
skuInfo={this.state.auditRow}
canEditable={this.canEditable}
onCancel={() => {
this.setState({ visibleAuditModal: false, auditRow: {} });
}}
onEdit={() => {
this.setState({ visibleAuditModal: false, auditRow: {} });
if (this.state.auditRow.type === 4) {
this.serviceVisbleChange(this.state.auditRow);
} else {
this.onUpdateInfo(this.state.auditRow);
}
}}
/>
{this.state.visibleAuditModal && (
<InfoAudit
visible={this.state.visibleAuditModal}
skuInfo={this.state.auditRow}
canEditable={this.canEditable}
onCancel={() => {
this.setState({ visibleAuditModal: false, auditRow: {} });
}}
onEdit={this.onEdit}
/>
)}
</PageHeaderWrapper>
);
}
......
......@@ -215,11 +215,7 @@ export function column() {
size="small"
className={styles.button}
onClick={() => {
if (row.type === 4) {
this.serviceVisbleChange(row);
} else {
this.onUpdateInfo(row);
}
this.serviceVisbleChange(row);
}}
>
修改
......@@ -364,6 +360,7 @@ export const ProcessEditData = (data, row) => {
id: data.id,
productType: data.productType,
pageProductType: row.productType,
productAttributeApplyList: data.productAttributeApplyList,
infoMation: {
...specsParams,
brandId: data.brandId,
......
......@@ -75,6 +75,11 @@
.pictureWrapper {
position: relative;
:global {
.ant-form-item-label > label {
word-break: break-all;
}
}
}
.pullImage {
position: absolute;
......@@ -164,3 +169,13 @@
}
}
}
.attrbox {
max-height: 384px;
overflow: hidden;
}
.attrboxMore {
max-height: max-content;
}
.btnMore {
text-align: center;
}
import React, { useState } from 'react';
import React from 'react';
import { Select, Form, InputNumber, Input, Button, Popover } from 'antd';
import commonStyle from '../common.less';
......@@ -108,7 +108,12 @@ export const CreateFormInput = props => {
return (
<>
{record.skuLink && (
<Button type="primary" size="small" onClick={() => onClickEvent('cloneImg', record)}>
<Button
type="primary"
size="small"
disabled={props.disabled}
onClick={() => onClickEvent('cloneImg', record)}
>
拉图片
</Button>
)}
......
......@@ -115,7 +115,18 @@ const EditFormTable = forwardRef((props, ref) => {
tableList: newDataSource,
});
};
const onClickEvent = () => {};
const onClickEvent = (type, row) => {
// 点击拉取京东图片功能
if (type === 'cloneImg') {
customer.onEventBus(type, row);
return;
}
// 修改sku名称
if (type === 'updateName') {
rowOnClickEvent(row);
}
};
useImperativeHandle(ref, () => ({
onCheck,
......@@ -174,8 +185,8 @@ const EditFormTable = forwardRef((props, ref) => {
<Form form={form} scrollToFirstError component={false}>
<EditableContext.Provider value={form}>
<Table
scroll={{ y: 300, x: 1000 }}
height={300}
scroll={{ y: 320, x: 1000 }}
height={320}
pagination={false}
size="small"
bordered
......
/* eslint-disable consistent-return */
import React, { forwardRef, useState, useEffect, useImperativeHandle } from 'react';
import { Form, Row, Col, Button } from 'antd';
import { unstable_batchedUpdates } from 'react-dom';
import { UpOutlined, DownOutlined } from '@ant-design/icons';
import styles from '../common.less';
import { apiGetAttribute } from '../service';
import CustomSelect from '@/components/CustomSelect';
const FormAttr = forwardRef((props, ref) => {
const [form] = Form.useForm();
const [isMore, setIsMome] = useState(false);
const [categoryAttrs, setCategoryAttrs] = useState([]);
const [skuOldAttr, setSkuOldAttr] = useState([]);
const [initAttrData, setInitAttrData] = useState({});
const formItemAttr = {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
const onChangeMore = () => {
setIsMome(!isMore);
};
// 验证是否失效属性(已失效的商品不显示)
const checkInAttrList = (id, categoryList) =>
categoryList.some(item => item.valueList.some(v => +v.id === +id));
// 获取初始化属性数据
const getInitAttrValue = categoryList => {
const skuAttr = props.initData.productAttributeApplyList?.productAttributeApplyList || [];
const obj = {
initValue: {},
};
const key = 'productAttributeApplyValueList';
skuAttr.forEach(item => {
if (item[key].length) {
let values = +item.optionType.code === 1 ? '' : [];
obj[item.productAttributeId] = [];
item[key].forEach(attr => {
const { attributeValueId, attributeValueName } = attr;
const json = {
attributeValueId,
attributeValueName,
name: attributeValueName,
};
if (attributeValueId === 0 || checkInAttrList(attributeValueId, categoryList)) {
const v = JSON.stringify(json);
if (attributeValueId === 0) {
obj[item.productAttributeId].push(json);
}
// eslint-disable-next-line no-unused-expressions
+item.optionType.code === 1 ? (values = v) : values.push(v);
}
});
obj.initValue[item.productAttributeId] = values;
}
});
return obj;
};
// 获取属性
const getAttribute = async categoryId => {
const res = await apiGetAttribute(categoryId);
if (res && res.data && res.data.length) {
let initValue = {
initValue: {},
};
if (props.initData) {
if (props.initData.productAttributeApplyList?.oldProductAttributeApplyList) {
const oattr = props.initData.productAttributeApplyList;
setSkuOldAttr((oattr && oattr.oldProductAttributeApplyList) || []);
}
if (props.initData.productAttributeApplyList?.productAttributeApplyList) {
initValue = getInitAttrValue(res.data);
}
}
res.data.forEach(item => {
item.valueList = item.valueList.map(v => ({
attributeValueId: v.id,
attributeValueName: v.name,
name: v.name,
}));
if (initValue[item.id] && initValue[item.id].length) {
item.valueList.push(...initValue[item.id]);
}
});
unstable_batchedUpdates(() => {
setInitAttrData(initValue.initValue);
setCategoryAttrs(res.data);
});
} else {
setInitAttrData({});
setCategoryAttrs([]);
}
};
// 获取下拉框类型
const getMode = optionType => (+optionType.code === 2 ? 'multiple' : 'default');
// 获取下拉框校验
const getAttrRules = k => {
if (+k.required.code === 1) {
return [
{
required: true,
type: +k.optionType.code === 2 ? 'array' : 'string',
message: '请选择',
},
];
}
return [];
};
// 处理下拉框返回值
const deal = attr => {
try {
const json = JSON.parse(attr);
if (json.attributeValueId) {
return json;
}
return { attributeValueName: json.name };
} catch {
return { attributeValueName: attr };
}
};
const onCheck = async () => {
try {
const values = await form.validateFields();
const attributeApplyList = [];
// eslint-disable-next-line no-restricted-syntax
for (const key in values) {
if (values.hasOwnProperty(key) && values[key]) {
let attrs = values[key];
if (Array.isArray(values[key])) {
attrs = [];
values[key].forEach(attr => {
if (typeof attr !== 'undefined') {
attrs.push(deal(attr));
}
});
} else {
const json = deal(values[key]);
json && (attrs = [json]);
}
attributeApplyList.push({
attributeId: key,
attributeApplyValueList: attrs,
});
}
}
return {
temp: 'attributeApplyList',
attributeApplyList,
};
} catch (errorInfo) {
return null;
}
};
useEffect(() => {
const ids = props.categoryIds;
if (ids && ids.length) {
getAttribute(ids[ids.length - 1]);
} else {
setInitAttrData({});
setCategoryAttrs([]);
}
}, [props.categoryIds]);
useImperativeHandle(ref, () => ({
onCheck,
reset: form.resetFields,
}));
return (
<>
<div className={styles.attrbox + (isMore ? styles.attrboxMore : '')}>
{categoryAttrs.length > 0 && (
<Form form={form} initialValues={initAttrData}>
<Row>
{categoryAttrs.map(k => (
<Col span={12} key={k.id}>
<Form.Item
label={k.name}
name={k.id}
{...formItemAttr}
key={k.id}
rules={getAttrRules(k)}
>
<CustomSelect
options={k.valueList || []}
isCustom={+k.supportCustomValue.code === 1}
mode={getMode(k.optionType)}
/>
</Form.Item>
</Col>
))}
</Row>
</Form>
)}
</div>
{categoryAttrs.length > 12 && (
<div className={styles.btnMore}>
<Button type="link" onClick={onChangeMore}>
{isMore ? (
<>
收起 <UpOutlined />
</>
) : (
<>
展示更多 <DownOutlined />
</>
)}
</Button>
</div>
)}
{skuOldAttr.length > 0 && (
<div>
<Row>注:以下商品属性已失效,请使用新的属性</Row>
<Row>
{skuOldAttr.map(s => (
<Col span={12} key={s.id}>
<Form.Item
label={s.productAttributeName}
{...formItemAttr}
required={false}
key={s.id}
>
{s.productAttributeApplyValueList.map(item => item.attributeValueName).join('')}
</Form.Item>
</Col>
))}
</Row>
</div>
)}
</>
);
});
export default FormAttr;
......@@ -83,9 +83,6 @@ const FormInformationBasic = forwardRef((props, ref) => {
}}
scrollToFirstError
>
{/* <Button type="primary" onClick={onCheck}>
测试
</Button> */}
<Form.Item
name="categoryId"
label="商品类目"
......@@ -93,8 +90,10 @@ const FormInformationBasic = forwardRef((props, ref) => {
>
<Cascader
placeholder="请选择商品类目!"
disabled={customer.isEdit && customer.isNormal}
showSearch={{ filter: filterCategoryOptions }}
fieldNames={{ label: 'name', value: 'id', children: 'children' }}
onChange={props.onCategoryChange}
options={newCategoryList[customer.productType]}
/>
</Form.Item>
......@@ -106,8 +105,8 @@ const FormInformationBasic = forwardRef((props, ref) => {
extra="若需新增品牌请联系业务员"
>
<Select
disabled={customer.isService}
showSearch
disabled={customer.isDisabled}
placeholder="请选择商品品牌"
filterOption={fileterBrandOptions}
>
......@@ -126,14 +125,9 @@ const FormInformationBasic = forwardRef((props, ref) => {
{ required: true, min: 2, message: '请输入最少两个字符的商品名称!', whitespace: true },
]}
>
<Input placeholder="请输入商品名称" />
<Input placeholder="请输入商品名称" disabled={customer.isDisabled} />
</Form.Item>
</Popover>
{customer.isJDGoods && (
<Button key="jdMsg" danger type="text">
*本列表的商品名称仅供搜索使用,不在前端作展示。若要修改APP端展示的商品名称,请在商品信息中修改。
</Button>
)}
{!customer.isCard && (
<Form.Item
name="character"
......
......@@ -58,7 +58,7 @@ const SpecificationTemplate = (props, _) => {
const handleChange = (val, option) => {
const optionSpecName = option ? option.specName : null;
form.setFieldsValue({ [selectName]: optionSpecName });
// onChange();
onChange();
};
const inputOnblurEvent = event => {
......@@ -77,11 +77,14 @@ const SpecificationTemplate = (props, _) => {
return;
}
addCallback();
onChange();
};
const bundlePlusRemoveSpecEvent = (removeCallback, fieldName) => {
removeCallback(fieldName);
form.setFieldsValue({
bacthFirst: undefined,
bacthSecon: undefined,
});
const timer = setTimeout(() => {
onChange();
clearTimeout(timer);
......@@ -92,7 +95,7 @@ const SpecificationTemplate = (props, _) => {
<>
<Form.Item name={formName} label={label}>
<Select
disabled={customer.isEdit}
disabled={customer.isEdit && customer.isNormal}
allowClear
options={specList}
style={{ width: 200 }}
......@@ -114,8 +117,9 @@ const SpecificationTemplate = (props, _) => {
{fields.map((field, index) => (
<Form.Item key={field.key} noStyle shouldUpdate={(prevValues, curValues) => false}>
{() => (
<Space key={field.key} align="baseline">
<Space key={`space_${field.key}`} align="baseline">
<Form.Item
key={`item_${field.key}`}
style={{ marginLeft: 10 }}
name={[field.name, specName]}
rules={[
......@@ -143,6 +147,7 @@ const SpecificationTemplate = (props, _) => {
</Form.Item>
{!(specDataList[index] && specDataList[index].id) && (
<MinusCircleOutlined
key={`minus_${field.key}`}
onClick={() => bundlePlusRemoveSpecEvent(remove, field.name)}
/>
)}
......@@ -150,8 +155,8 @@ const SpecificationTemplate = (props, _) => {
)}
</Form.Item>
))}
{fields.length < 3 && (
<Form.Item noStyle>
{(!customer.isCard || fields.length < 3) && !customer.isDisabled && (
<Form.Item noStyle key="btnpush">
<Button
style={{ marginLeft: 10, marginBottom: 24 }}
type="dashed"
......@@ -202,7 +207,12 @@ const CreateBatchFormItems = ({ specInitValue, batchChange, editRef, defaultColu
fieldNames={{ label: 'secondSpecValue', value: 'secondSpecValue' }}
/>
{formItems.concat(
<Button key="batch" type="primary" onClick={batchChange}>
<Button
key="batch"
type="primary"
disabled={customer.isEdit && customer.isNormal}
onClick={batchChange}
>
批量设置
</Button>,
)}
......@@ -225,20 +235,54 @@ const FormPriceOrStock = forwardRef((props, ref) => {
const [tableData, setTableData] = useState([]);
const [mergeTable, setMergeTable] = useState(false);
const insertSpecID = items => {
const sids = items.filter(item => item.id);
if (sids.length !== skuList.length) {
let i = 0;
const ids = skuList.reduce((prev, cur) => {
if (!sids.includes(cur.id)) {
prev.push(cur.id);
}
return prev;
}, []);
items.forEach(item => {
if (!item.id && i < ids.length) {
item.id = ids[i++];
}
});
}
};
const onCheck = async () => {
try {
const setMealContent = await packageRef.current.onCheck();
let setMealContent = '';
if (customer.isCard) {
setMealContent = await packageRef.current.onCheck();
}
const values = await form.validateFields();
if (!values.firstSpecValue || !values.firstSpecValue.length) {
values.firstSpecId = null;
values.firstSpec = '';
}
if (!values.secondSpecValue || !values.secondSpecValue.length) {
values.secondSpecId = null;
values.secondSpec = '';
}
const items = await editRef.current.onCheck();
if (!setMealContent) {
if (customer.isCard && !setMealContent) {
notification.open({
message: '提示',
description: '请添加正确的套餐信息!',
});
return null;
}
if (items && setMealContent) {
return { ...values, items, setMealContent, temp: 'infoSpecData' };
if (items && items.length) {
if (customer.isEdit && skuList.length) {
insertSpecID(items);
}
const obj = { ...values, items, temp: 'infoSpecData' };
customer.isCard && setMealContent && (obj.setMealContent = setMealContent);
return obj;
}
notification.open({
message: '提示',
......@@ -267,7 +311,6 @@ const FormPriceOrStock = forwardRef((props, ref) => {
inputType: 'text',
});
}
const dynamicColumns = [...columsData, ...StaticColumns(customer)];
setDefaultColumns(dynamicColumns);
};
......@@ -278,8 +321,10 @@ const FormPriceOrStock = forwardRef((props, ref) => {
const cleanValues = {
firstValues: cleanArray(values.firstSpecValue || []),
secondValues: cleanArray(values.secondSpecValue || []),
firstSpecId: values.firstSpecId,
secondSpecId: values.secondSpecId,
firstSpecId:
values.firstSpecValue && values.firstSpecValue.length ? values.firstSpecId : null,
secondSpecId:
values.secondSpecValue && values.secondSpecValue.length ? values.secondSpecId : null,
};
const { inIdList: fisrtInIdList, noIdList: fisrtNoIdList } = filterSkuNotIdList(
......@@ -288,7 +333,6 @@ const FormPriceOrStock = forwardRef((props, ref) => {
const { inIdList: secndInIdList, noIdList: secndNoIdList } = filterSkuNotIdList(
cleanValues.secondValues,
);
const createSkuList = createProductData(
{
firstSpecId: cleanValues.firstSpecId,
......@@ -299,23 +343,25 @@ const FormPriceOrStock = forwardRef((props, ref) => {
secndNoIdList,
},
customer.isEdit,
skuList,
);
CreateColumnsEvent(values);
// 没有规格默认创建一条数据
if (!cleanValues.firstSpecId && !createSkuList.secondSpecId) {
setTableData([...createSkuList]);
return;
}
// 是否合并单元格
setMergeTable(Boolean(cleanValues.secondValues.length));
setTableData(fliterSkuListSortData([...skuList, ...createSkuList]));
setTableData(fliterSkuListSortData([...createSkuList]));
} catch (error) {
console.log(error);
}
};
const batchChange = () => {
const batchItem = form.getFieldValue('batchItem');
const bacthFirst = form.getFieldValue('bacthFirst');
const bacthSecon = form.getFieldValue('bacthSecon');
const values = form.getFieldsValue();
const { batchItem, bacthFirst, bacthSecon } = values;
const resetObject = batchTableSourceData({ batchItem, tableData, bacthSecon, bacthFirst });
setTableData(resetObject);
};
......@@ -323,6 +369,8 @@ const FormPriceOrStock = forwardRef((props, ref) => {
const onSpecificationEvent = async () => {
try {
const values = await form.validateFields();
console.log('values :>> ', values);
console.log('cleanArray(values.secondSpecValue) :>> ', cleanArray(values.secondSpecValue));
const cleanValues = {
firstSpec: values.firstSpec,
firstSpecId: values.firstSpecId,
......@@ -348,10 +396,12 @@ const FormPriceOrStock = forwardRef((props, ref) => {
);
onSpecChange(firstSpecValueList);
}
onFinish();
};
const seconOnChangeEvent = async () => {
await onSpecificationEvent();
onFinish();
};
useImperativeHandle(ref, () => ({
......@@ -400,16 +450,18 @@ const FormPriceOrStock = forwardRef((props, ref) => {
specList={specList}
specDataList={specInitValue.secondSpecValue}
/>
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: 20 }}>
{/* <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 20 }}>
<Button type="primary" onClick={onFinish}>
生成商品信息
</Button>
</div> */}
<div>
<CreateBatchFormItems
batchChange={batchChange}
specInitValue={specInitValue}
defaultColumns={defaultColumns}
/>
</div>
<CreateBatchFormItems
batchChange={batchChange}
specInitValue={specInitValue}
defaultColumns={defaultColumns}
/>
</Form>
<EditFormTable
ref={editRef}
......@@ -420,8 +472,8 @@ const FormPriceOrStock = forwardRef((props, ref) => {
/>
{customer.isCard && (
<>
<Title title="套餐内容" />
<FormPackage ref={packageRef} initData={tableData} />
<Title title="套餐内容" key="tctitle" />
<FormPackage ref={packageRef} initData={tableData} key="tc" />
</>
)}
</>
......
......@@ -92,19 +92,14 @@ const FormRuleSetting = forwardRef((props, ref) => {
>
<Form.Item name="purchaseTime" label="购买时间" {...rangeConfig}>
<RangePicker
showTime={{
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
}}
format="YYYY-MM-DD HH:mm:ss"
defaultPickerValue={[nowDateTime, nowDateTimeEnd]}
/>
</Form.Item>
<Form.Item name="useTime" label="有效期" {...rangeConfig}>
<RangePicker
showTime={{
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
}}
format="YYYY-MM-DD HH:mm:ss"
defaultPickerValue={[nowDateTime, nowDateTimeEnd]}
/>
</Form.Item>
<Form.Item
......
/* eslint-disable guard-for-in */
/* eslint-disable no-restricted-syntax */
import React, { useState, useEffect, useContext, forwardRef, useImperativeHandle } from 'react';
import { Form, Button } from 'antd';
import { ServiceContext } from '../context';
......@@ -15,6 +17,9 @@ const FormRuleVPictures = forwardRef((props, ref) => {
const [form] = Form.useForm();
const customer = useContext(ServiceContext);
const typeConfig = TaskList(customer.canAddService, customer.canAddNormal);
const [{ imgConfig }] = typeConfig.filter(item => item.type === customer.productType);
useEffect(() => {
if (customer.isEdit) {
if (editData) {
......@@ -64,7 +69,16 @@ const FormRuleVPictures = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
onCheck,
setFieldsValue: form.setFieldsValue,
setFieldsValue: obj => {
setDetailImageList(obj.detailImageList || []);
for (const key in obj.imageList) {
if (!obj.imageList[key]) {
obj.imageList[key] = [];
}
}
setImageList(obj.imageList || {});
form.setFieldsValue(obj);
},
getFieldsValue: form.getFieldsValue,
reset: () => {
form.resetFields();
......@@ -97,6 +111,14 @@ const FormRuleVPictures = forwardRef((props, ref) => {
});
};
// 拉取公共图片
const onPullCommonImg = key => {
const cimg = form.getFieldValue('commonImageList');
const obj = { ...imageList };
obj[key] = cimg;
setImageList(obj);
};
const onDetailSuccessImageList = imgList => {
setDetailImageList(imgList);
form.setFieldsValue({
......@@ -104,11 +126,13 @@ const FormRuleVPictures = forwardRef((props, ref) => {
});
};
const [{ imgConfig }] = TaskList.filter(item => item.type === customer.productType);
return (
<Form
form={form}
{...formItemLayout}
labelCol={{ flex: '110px' }}
labelAlign="right"
labelWrap
colon
initialValues={{
commonImageList: [],
cardImageList: [],
......@@ -141,9 +165,12 @@ const FormRuleVPictures = forwardRef((props, ref) => {
]}
>
<UploadImage
disabled={customer.isService}
multiple={false}
multiple={!customer.isCard}
maxWidth={customer.isCard ? 0 : 1200}
maxHeight={customer.isCard ? 0 : 1200}
superTips="公共滑动图尺寸不可大于 1200*1200"
name="commonImageList"
disabled={customer.isDisabled}
limit={imgConfig.commonImageList.limit}
pictures={commonImageList}
setPictureList={list => onCommonSuccessEvent(list)}
......@@ -163,9 +190,9 @@ const FormRuleVPictures = forwardRef((props, ref) => {
]}
>
<UploadImage
disabled={customer.isService}
name="cardImageList"
limit={imgConfig.cardImageList.limit}
disabled={customer.isDisabled}
pictures={cardImageList}
setPictureList={list => onCardSuccessImageList(list)}
/>
......@@ -184,16 +211,23 @@ const FormRuleVPictures = forwardRef((props, ref) => {
extra={imgConfig.imageList.renderExtra()}
>
<UploadImage
disabled={customer.isService}
name={key}
limit={11}
disabled={customer.isDisabled}
pictures={imageList[key]}
setPictureList={list => onPictureSuccessEvent(list, key)}
/>
</Form.Item>
<Button className={commonStyle.pullImage} type="primary">
拉取公共图
</Button>
{!imageList[key]?.length && (
<Button
disabled={imageList[key]?.length}
className={commonStyle.pullImage}
onClick={() => onPullCommonImg(key)}
type="primary"
>
拉取公共图
</Button>
)}
</div>
))}
<Form.Item
......@@ -209,9 +243,11 @@ const FormRuleVPictures = forwardRef((props, ref) => {
extra={imgConfig.detailImageList.renderExtra()}
>
<UploadImage
disabled={customer.isService}
limit={imgConfig.detailImageList.limit}
maxWidth={customer.isCard ? 0 : 800}
superTips="详情图宽度不可大于800"
name="detailImageList"
disabled={customer.isDisabled}
pictures={detailImageList}
setPictureList={list => onDetailSuccessImageList(list)}
/>
......
......@@ -5,6 +5,7 @@ import commonStyle from '../common.less';
export const TaskTypeSelect = props => {
const customer = useContext(ServiceContext);
const typeConfig = TaskList(customer.canAddService, customer.canAddNormal);
const selectTabs = task => {
if (!customer.isEdit) {
props.onChange(task);
......@@ -13,7 +14,7 @@ export const TaskTypeSelect = props => {
return (
<div className={commonStyle.prodcutContent}>
{TaskList.map(task => {
{typeConfig.map(task => {
const activeClassName = props.productType === task.type ? commonStyle.activeCard : '';
if (task.hide) return null;
return (
......
......@@ -72,26 +72,83 @@ const UploadImage = forwardRef((props, ref) => {
const freshFiles = fileList?.filter(ele => ele.uid !== file.uid);
bundleChange(freshFiles);
};
const checkFile = file =>
new Promise(resolve => {
const curType = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
const fileType = ['jpg', 'jpeg', 'png'];
if (!fileType.includes(curType)) {
notification.open({
message: file.name,
description: '图片格式须为jpg、jpeg、png!',
});
return resolve(null);
const cleanArray = (actual = []) =>
actual.reduce((prev, cur) => {
cur && prev.push(cur);
return prev;
}, []);
const warningTip = description => {
notification.warning({
message: '图片上传失败',
description,
});
};
const getBase64 = (img, callback) => {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
};
const ImageInfo = file =>
new Promise((resolve, reject) => {
const LtMB = file.size / 1024 / 1024;
if (LtMB > 2) {
warningTip(`[${file.name}] 图片不可以大于2MB`);
resolve(null);
}
if (file.size > MAX_FILE_SIZE * UNIT) {
notification.open({
message: file.name,
description: `单个图片大小不能超过${MAX_FILE_SIZE}M!`,
getBase64(file, url => {
const image = new Image();
image.addEventListener('load', () => {
const { width } = image;
const { height } = image;
file.width = width;
file.height = height;
file.LtMB = LtMB;
resolve(file);
});
image.addEventListener('error', () => {
warningTip(`${file.name}图片上传失败!`);
resolve(null);
});
return resolve(null);
image.src = url;
});
});
const CheckImageInfoList = async files => {
const promiseImage = files.map(file => ImageInfo(file));
const clearImage = await Promise.all(promiseImage);
return cleanArray(clearImage);
};
const isUploadNext = async imgFileList => {
const filterImage = imgFileList.filter(img => {
if (
(imgOptions.maxWidth && img.width > imgOptions.maxWidth) ||
(imgOptions.maxHeight && img.height > imgOptions.maxHeight)
) {
warningTip(`[${img.name}] ${imgOptions.superTips}`);
return false;
}
return true;
});
return filterImage;
};
const checkFile = files => {
const fileType = ['jpg', 'jpeg', 'png'];
const filterImage = files.filter(file => {
const curType = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
if (!fileType.includes(curType)) {
warningTip('图片格式须为jpg、jpeg、png!');
return false;
}
return resolve(file);
return true;
});
return filterImage;
};
const imageLoading = (file, ret) =>
new Promise(resolve => {
......@@ -119,12 +176,14 @@ const UploadImage = forwardRef((props, ref) => {
});
return Upload.LIST_IGNORE;
}
const fileAll = fileArray.map(item => checkFile(item));
const checkFiles = (await Promise.all(fileAll)).filter(item => item !== null);
const flies = checkFile(fileArray);
const optionsArray = await CheckImageInfoList(flies);
const checkFiles = await isUploadNext(optionsArray);
try {
if (checkFiles.length) {
setUploadLoading(true);
const res = await merchantUpload(checkFiles);
console.log('res :>> ', res);
if (res.data) {
const proFiles = (res.data || []).map((urlItem, urlIndex) =>
imageLoading(checkFiles[urlIndex], urlItem),
......@@ -176,10 +235,12 @@ const UploadImage = forwardRef((props, ref) => {
onClick={() => handlePreview(item)}
/> */}
<EyeOutlined className={styles.maskIcon} onClick={() => handlePreview(item)} />
<DeleteOutlined
className={styles.maskIcon}
onClick={() => handleRemove(item)}
/>
{!disabled && (
<DeleteOutlined
className={styles.maskIcon}
onClick={() => handleRemove(item)}
/>
)}
{/* <Icon
type="delete"
className={styles.maskIcon}
......
......@@ -7,12 +7,12 @@ export const formItemLayout = {
},
};
export const TaskList = [
export const TaskList = (canAddService, canAddNormal) => [
{
name: '实体商品',
type: 1,
desc: '物流发货',
hide: true,
hide: !canAddNormal,
imgConfig: {
commonImageList: {
title: '公共滑动图',
......@@ -37,7 +37,7 @@ export const TaskList = [
name: '虚拟商品',
type: 2,
desc: '无需物流',
hide: true,
hide: !canAddNormal,
imgConfig: {
commonImageList: {
title: '公共滑动图',
......@@ -58,38 +58,11 @@ export const TaskList = [
},
},
},
// {
// name: '电子卡卷',
// type: 3,
// desc: '无需物流',
// hide: true,
// imgConfig: {
// commonImageList: {
// title: '封面图片',
// rule: true,
// limit: 11,
// renderExtra(leng) {
// return `建议尺寸: ##宽##高 (${leng} / 1) `;
// },
// },
// imageList: {
// rule: true,
// limit: 1,
// },
// detailImageList: {
// title: '商品图片',
// rule: true,
// limit: null,
// renderExtra() {
// return '请上传商品图!';
// },
// },
// },
// },
{
name: '电子卡卷',
type: 4,
desc: '无需物流',
hide: !canAddService,
imgConfig: {
commonImageList: {
title: '封面图片',
......@@ -165,7 +138,7 @@ export const StaticColumns = customer => [
min: 0,
},
roleRules: { required: true },
disabeldRender: () => customer.isJDGoods,
disabeldRender: () => customer.isDisabled,
},
{
title: '佣金费率',
......@@ -188,7 +161,7 @@ export const StaticColumns = customer => [
min: 0,
},
roleRules: { required: true },
// disabeldRender: () => customer.isService,
disabeldRender: () => customer.isDisabled,
},
{
title: '销售价',
......@@ -201,6 +174,7 @@ export const StaticColumns = customer => [
precision: 2,
min: 0,
},
disabeldRender: () => customer.isDisabled,
},
{
title: '重量(kg)',
......@@ -219,7 +193,7 @@ export const StaticColumns = customer => [
precision: 3,
max: 999999.999,
},
// disabeldRender: () => customer.isService,
disabeldRender: () => customer.isDisabled,
},
{
title: '库存',
......@@ -236,7 +210,10 @@ export const StaticColumns = customer => [
min: 0,
},
roleRules: { required: true },
disabeldRender: v => v.id && customer.isService,
disabeldRender: record => {
if (record.stock === null) return false;
return customer.isEdit && customer.isNormal;
},
},
{
title: '库存预警',
......@@ -244,13 +221,12 @@ export const StaticColumns = customer => [
editable: true,
batchRole: [1],
role: [1, 4],
roleRules: { required: true },
roleProps: {
min: 0,
precision: 0,
maxLength: 5,
},
// disabeldRender: () => customer.isService,
disabeldRender: () => customer.isDisabled,
},
{
title: '商品自编码',
......@@ -259,7 +235,7 @@ export const StaticColumns = customer => [
role: [1, 2],
inputType: 'input',
roleRules: { required: true },
disabeldRender: () => customer.isService,
disabeldRender: () => customer.isDisabled,
},
{
title: '京东链接',
......@@ -268,7 +244,7 @@ export const StaticColumns = customer => [
role: [1, 2],
inputType: 'input',
roleRules: { required: false },
disabeldRender: () => customer.isService,
disabeldRender: () => customer.isDisabled,
},
{
title: 'sku名称',
......@@ -277,6 +253,7 @@ export const StaticColumns = customer => [
role: customer.isEdit && customer.isJDGoods ? [1, 2] : [],
inputType: 'btnText',
roleRules: { required: false },
disabeldRender: () => customer.isDisabled,
},
{
title: '操作',
......@@ -286,8 +263,10 @@ export const StaticColumns = customer => [
inputType: 'option',
roleProps: {
isJDGoods: customer.isJDGoods,
disabled: customer.isDisabled,
min: 0,
},
roleRules: { required: false },
disabeldRender: () => customer.isDisabled,
},
];
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { Spin, Button, Modal, message, notification } from 'antd';
import { ConsoleSqlOutlined } from '@ant-design/icons';
import { Title, WrapperContainer } from './components/CommonTemplate';
import { TaskTypeSelect } from './components/TaskTypeSelect';
import FormInformationBasic from './components/FormInformationBasic';
......@@ -8,12 +7,12 @@ import FormPriceOrStock from './components/FormPriceOrStock';
import FormRuleSetting from './components/FormRuleSetting';
import FormRuleVPictures from './components/FormRuleVPictures';
import FormSettlementOthers from './components/FormSettlementOthers';
import FormAttr from './components/FormAttr';
import {
merchantBrandList,
merchantSpecList,
afterSalesAddrsPage,
merchantgetJdPicList,
supplierListQuery,
shopGetBySupplierId,
merchantProductAdd,
merchantProductEdit,
......@@ -21,6 +20,7 @@ import {
} from './service';
import { isUrl, filterSendData, clearCurrent } from './utils';
import { ServiceContext } from './context';
import { GOOD_MANAGE } from '@/../config/permission.config';
/**
* 服务商品改造-商品模块
......@@ -28,17 +28,21 @@ import { ServiceContext } from './context';
* @returns ReactDOM
*/
const ServiceGoods = options => {
const { SourceData, categoryList, virtualCategoryList, specListData } = options;
const { SourceData, categoryList, virtualCategoryList, specListData, permissions } = options;
const canAddService = permissions[GOOD_MANAGE.ADD_SERVICE_GOODS];
const canAddNormal = permissions[GOOD_MANAGE.ADD_NORMAL_GOODS];
const basicRef = useRef(null);
const stockRef = useRef(null);
const settingRef = useRef(null);
const picturesRef = useRef(null);
const settleOtrRef = useRef(null);
const attrRef = useRef(null);
const [pageId, setPageId] = useState(null);
const [categoryIds, setCategoryIds] = useState([]); // 商品品类ID
const [isEdit, setIsEdit] = useState(false); // 是否是编辑状态
const [productType, setProductType] = useState(4); // 商品状态
const [productType, setProductType] = useState(canAddNormal ? 1 : 4); // 商品状态
const [pageLoading, setPageLoading] = useState(false); // 页面加载状态
const [afterAddressList, setAfterAddressList] = useState([]); // 售后地址
const [supplierIdList, setSupplierIdList] = useState([]); // 适用们店列表
......@@ -47,8 +51,14 @@ const ServiceGoods = options => {
const [specList, setSpecList] = useState([]); // 规格列表
const [editData, setEditData] = useState({}); // 编辑保存数据
const [newCategoryList, setNewCategoryList] = useState({});
// const [shopList, setShopList] = useState([]); // 供应商列表
const [checkFormList] = useState([basicRef, stockRef, settingRef, settleOtrRef, picturesRef]);
const [checkFormList] = useState([
basicRef,
attrRef,
stockRef,
settingRef,
settleOtrRef,
picturesRef,
]);
const [specKeyList, setSpecKeyList] = useState([]); // 记录一级规格key字段
......@@ -56,6 +66,7 @@ const ServiceGoods = options => {
const productChange = task => {
setProductType(task.type);
setCategoryIds([]);
const timer = setTimeout(() => {
resetForm();
clearTimeout(timer);
......@@ -94,13 +105,6 @@ const ServiceGoods = options => {
}
};
// const getSupplierListResponse = async () => {
// if (!shopList.length) {
// const result = await supplierListQuery();
// console.log('=================>result', result);
// setShopList(result.data);
// }
// };
const sendMerchantProductHttpRequest = async sendData => {
try {
setPageLoading(true);
......@@ -125,7 +129,6 @@ const ServiceGoods = options => {
};
const shopGetByProductType = async type => {
console.log(newCategoryList[type]);
if (!newCategoryList[type]?.length) {
const result = await getByProductType(type);
setNewCategoryList({
......@@ -133,12 +136,12 @@ const ServiceGoods = options => {
[type]: result.data || [],
});
}
// console.log(result);
};
const submitEvent = async () => {
const checkPromiseList = clearCurrent(checkFormList).map(({ current }) => current.onCheck());
const resuslt = await Promise.all(checkPromiseList);
console.log('resuslt :>> ', resuslt);
if (!resuslt.includes(null)) {
const params = resuslt.reduce((origin, item) => {
const { temp, ...other } = item;
......@@ -149,6 +152,7 @@ const ServiceGoods = options => {
if (isEdit) {
sendData.id = pageId;
}
console.log('sendData :>> ', sendData);
sendMerchantProductHttpRequest(sendData);
}
};
......@@ -160,11 +164,9 @@ const ServiceGoods = options => {
const detailList = result.detailList || [];
const newImageList = imageList[result.firstSpecValue];
const carouseList = result.carouseList || [];
imageList[result.firstSpecValue] = newImageList
? [...newImageList, ...carouseList]
: carouseList;
imageList[result.firstSpecValue] =
(newImageList ? [...newImageList, ...carouseList] : carouseList) || [];
picturesRef.current.setFieldsValue({
// [`imageList[${data.firstSpecValue}]`]: this.state.colorImg[data.firstSpecValue],
imageList,
detailImageList: [...detailImageList, ...detailList],
});
......@@ -178,7 +180,6 @@ const ServiceGoods = options => {
}
setPageLoading(true);
await shopGetBySupplierIdResponse();
// await getSupplierListResponse();
await getMerchantBrandList();
await getAfterSalesAddrsPage();
await getMerchantSpecList();
......@@ -186,7 +187,7 @@ const ServiceGoods = options => {
setEditData(SourceData);
setPageId(SourceData.id);
setProductType(SourceData.productType);
// changeCheckList(SourceData.productType);
setCategoryIds(SourceData.infoMation.categoryId || []);
setIsEdit(true);
}
setPageLoading(false);
......@@ -199,6 +200,10 @@ const ServiceGoods = options => {
}
}, [productType, options.visible]);
useEffect(() => {
setProductType(canAddNormal ? 1 : 4);
}, [canAddNormal]);
const onSpecCommonImgEvent = useCallback(
keys => {
setSpecKeyList(keys);
......@@ -225,13 +230,21 @@ const ServiceGoods = options => {
});
}
};
const onCategoryChange = e => {
setCategoryIds(e);
};
const providerValue = {
pageId,
isEdit,
productType,
canAddService, // 是否可以添加服务商品(电子卡券)
canAddNormal, // 是否可以添加实物商品
isCard: productType === 4,
isService: SourceData.state && SourceData.state !== 4,
// 0, "商品删除" 1, "新建" 2, "提交审核" 3, "待审核" 4, "驳回" 5, "未上架" 6, "已上架" 7, "已下架"
isNormal: SourceData.state && SourceData.state !== 4, // 商品不是驳回状态
// 当商品进行编辑 & 类型不为电子卡券 & 商品状态不为驳回 禁用当前功能
isDisabled: isEdit && productType !== 4 && SourceData.state && SourceData.state !== 4,
isJDGoods: isEdit && SourceData.pageProductType && +SourceData.pageProductType !== 1,
onEventBus,
};
......@@ -270,8 +283,14 @@ const ServiceGoods = options => {
brandList={brandList}
afterAddressList={afterAddressList}
specListData={specListData}
onCategoryChange={onCategoryChange}
/>
{[1, 2].includes(productType) && [
<Title title="商品属性" key="attrtitle" />,
<FormAttr key="attr" ref={attrRef} categoryIds={categoryIds} initData={editData} />,
]}
<Title title="价格与库存" />
<FormPriceOrStock
ref={stockRef}
......
......@@ -97,3 +97,9 @@ export const getByProductType = type =>
prefix: goodsApi,
headers,
});
// 获取类目关联属性
export const apiGetAttribute = categoryId =>
request.get(`/api/kdsp/category/template/ref/attribute/detail?categoryId=${categoryId}`, {
prefix: goodsApi,
});
......@@ -107,10 +107,10 @@ const filterItems = (type, props) => {
export const filterSendData = (type, params) => {
console.log('===============>生成数据', params);
const { infoMation, infoImageData } = params;
const { infoMation, infoImageData, attributeApplyList } = params;
const items = filterItems(type, params);
const commonImageList = type === 4 ? [] : infoImageData.commonImageList;
return {
const obj = {
type,
items,
name: infoMation.name,
......@@ -123,6 +123,10 @@ export const filterSendData = (type, params) => {
detailImageList: infoImageData.detailImageList,
commonImageList,
};
if (attributeApplyList && attributeApplyList.attributeApplyList) {
obj.attributeApplyList = attributeApplyList.attributeApplyList;
}
return obj;
};
export const fliterSkuListSortData = list => {
......@@ -178,29 +182,38 @@ const createInitSkuItems = () => ({
name: null,
});
export const createSkuListData = (first, second, firstSpecId, secondSpecId) => {
const getSecordValue = (firstSpecValue, sec, skuList = []) =>
skuList.find(
sku =>
sku.firstSpecValue === firstSpecValue &&
(!sku.secondSpecValue || sku.secondSpecValue === sec.secondSpecValue),
);
export const createSkuListData = (first, second, firstSpecId, secondSpecId, skuList) => {
const list = [];
const skuItem = createInitSkuItems();
console.log(first, second, firstSpecId, secondSpecId);
if (first && first.length) {
// 一级规格有值时,生成的编辑表格
first.forEach(fir => {
const copy = { ...skuItem };
let copy = { ...skuItem };
copy.firstSpecId = firstSpecId;
copy.firstSpecValue = fir.firstSpecValue;
// console.log(copy);
if (second.length) {
second.forEach(sec => {
const copySec = { ...copy };
const v = getSecordValue(fir.firstSpecValue, sec, skuList);
const copySec = v || { ...copy };
copySec.secondSpecId = secondSpecId;
copySec.secondSpecValue = sec.secondSpecValue;
delete copySec.rowSpanCount;
list.push(copySec);
});
return;
}
const v = getSecordValue(`${fir.firstSpecValue}`, {}, skuList);
if (v) {
copy = { ...v };
}
list.push(copy);
});
} else if (second && second.length) {
......@@ -211,6 +224,8 @@ export const createSkuListData = (first, second, firstSpecId, secondSpecId) => {
copy.secondSpecValue = sec.secondSpecValue;
list.push(copy);
});
} else if (skuList && skuList.length) {
list.push(...skuList);
} else {
// 缺少一级和二级规格时生成的编辑表格
list.push(skuItem);
......@@ -218,7 +233,7 @@ export const createSkuListData = (first, second, firstSpecId, secondSpecId) => {
return list;
};
export const createProductData = (props, isEdit) => {
export const createProductData = (props, isEdit, skuList) => {
const {
firstSpecId,
secondSpecId,
......@@ -227,20 +242,13 @@ export const createProductData = (props, isEdit) => {
fisrtInIdList,
secndInIdList,
} = props;
const newFirstList = fisrtNoIdList.concat(fisrtInIdList || []);
let list = [];
// if (!isFirstSame && !isSecondSame) {
if (!isEdit) {
list = createSkuListData(fisrtNoIdList, secndNoIdList, firstSpecId, secondSpecId);
if (isEdit) {
const newFirstList = fisrtNoIdList.concat(fisrtInIdList || []);
const newSecondList = secndInIdList.concat(secndNoIdList || []);
list = createSkuListData(newFirstList, newSecondList, firstSpecId, secondSpecId, skuList);
} else {
const list1 = fisrtNoIdList.length
? createSkuListData(fisrtNoIdList, secndInIdList, firstSpecId, secondSpecId)
: [];
const list2 = secndNoIdList.length
? createSkuListData(newFirstList, secndNoIdList, firstSpecId, secondSpecId)
: [];
list = [...list1, ...list2];
list = createSkuListData(fisrtNoIdList, secndNoIdList, firstSpecId, secondSpecId);
}
// }
return list;
};
......@@ -94,7 +94,9 @@ class Socket extends EventEmitter {
}
}, 5000);
};
reconnect();
if (process.env.NODE_ENV === 'production') {
reconnect();
}
};
onerror = e => {
......@@ -126,9 +128,9 @@ class Socket extends EventEmitter {
// 保持连接-默认每3分钟重置一下服务器关闭时间
heartBeat(time) {
console.log('ws: call heartBeat', new Date().getTime());
// console.log('ws: call heartBeat', new Date().getTime());
this.heartBeatTimer = setTimeout(() => {
console.log('ws: sent heart beat', new Date().getTime());
// console.log('ws: sent heart beat', new Date().getTime());
this.sendMessage('HeartBeat');
this.heartBeat(time);
}, time || 45000);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment