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

feat: 添加商品属性

parent 0a13076e
...@@ -2,19 +2,19 @@ const isProduction = process.env.NODE_ENV === 'production'; ...@@ -2,19 +2,19 @@ const isProduction = process.env.NODE_ENV === 'production';
const isPre = process.env.PRE_ENV === 'pre'; const isPre = process.env.PRE_ENV === 'pre';
const envAPi = { const envAPi = {
api: 'https://security-xyqb.liangkebang.net', //'https://security-xyqb.liangkebang.net', api: 'https://security-ds.liangkebang.net', //'https://security-ds.liangkebang.net',
kdspOpApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspOpApi: 'https://sc-merchant-api-ds.liangkebang.net',
kdspApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspApi: 'https://sc-merchant-api-ds.liangkebang.net',
goodsApi: 'https://sc-merchant-api-xyqb.liangkebang.net', goodsApi: 'https://sc-merchant-api-ds.liangkebang.net',
// kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net', // kdspOpApi: 'https://kdsp-operation-ds.liangkebang.net',
// kdspApi: 'https://sc-op-api-xyqb.liangkebang.net', // kdspApi: 'https://sc-op-api-ds.liangkebang.net',
// goodsApi: 'https://sc-op-api-xyqb.liangkebang.net', // goodsApi: 'https://sc-op-api-ds.liangkebang.net',
querysApi: 'https://sc-merchant-api-sc.liangkebang.net', querysApi: 'https://sc-merchant-api-ds.liangkebang.net',
// goodsApi: '//192.168.188.111:7000', // goodsApi: '//192.168.188.111:7000',
prologueDomain: 'https://mall-sc.liangkebang.net', prologueDomain: 'https://mall-ds.liangkebang.net',
// qiniuHost: 'https://appsync.lkbang.net', // qiniuHost: 'https://appsync.lkbang.net',
qiniuHost: 'https://kdspstatic.q-gp.com/', qiniuHost: 'https://kdspstatic.q-gp.com/',
opapiHost: 'https://opapi-sc.liangkebang.net', opapiHost: 'https://opapi-ds.liangkebang.net',
}; };
const prodApi = { const prodApi = {
......
...@@ -69,16 +69,25 @@ class goodsManage extends Component { ...@@ -69,16 +69,25 @@ class goodsManage extends Component {
productType: 1, productType: 1,
confirmLoading: false, confirmLoading: false,
afterAddressList: {}, afterAddressList: {},
categoryAttrs: [], // 获取类目下属性
}; };
componentDidMount() { componentDidMount() {
this.getSpecData(); this.getSpecData();
this.getBrandData(); this.getBrandData();
this.getAfterAddressData(); this.getAfterAddressData();
this.getAttribute();
} }
componentWillReceiveProps() { componentWillReceiveProps(nextProps) {
if (nextProps.visible && this.state.categoryAttrs.length < 1) {
const { initData = {} } = this.props;
const isEdit = Object.keys(initData).length !== 0;
if (isEdit) {
this.getAttribute(
initData.thirdCategoryId || initData.secondCategoryId || initData.firstCategoryId,
);
}
}
this.setState({ isCancel: false }); this.setState({ isCancel: false });
} }
...@@ -209,14 +218,20 @@ class goodsManage extends Component { ...@@ -209,14 +218,20 @@ class goodsManage extends Component {
// 获取属性 // 获取属性
getAttribute = async categoryId => { getAttribute = async categoryId => {
console.log('categoryId :>> ', categoryId); console.log('categoryId :>> ', categoryId);
const res = await apiGetAttribute({ const res = await apiGetAttribute(categoryId);
categoryId,
});
console.log('res :>> ', res); console.log('res :>> ', res);
let categoryAttrs = [];
if (res && res.data && res.data.length) {
categoryAttrs = res.data;
}
this.setState({
categoryAttrs,
});
}; };
treeChange = value => { treeChange = value => {
const cid = value[value.length - 1]; const cid = value[value.length - 1];
console.log('cid :>> ', cid);
this.setState({ categoryId: cid, initCascader: value }); this.setState({ categoryId: cid, initCascader: value });
this.getAttribute(cid); this.getAttribute(cid);
}; };
...@@ -372,6 +387,7 @@ class goodsManage extends Component { ...@@ -372,6 +387,7 @@ class goodsManage extends Component {
} = this.props; } = this.props;
const { editData, productType } = this.state; const { editData, productType } = this.state;
validateFields(async (errors, values) => { validateFields(async (errors, values) => {
console.log('values :>> ', values);
if (!values.afterAddressId) { if (!values.afterAddressId) {
notification.error({ notification.error({
message: '请选择售后地址', message: '请选择售后地址',
...@@ -403,6 +419,30 @@ class goodsManage extends Component { ...@@ -403,6 +419,30 @@ class goodsManage extends Component {
}); });
} }
}); });
const attributeApplyList = [];
values.attributeApplyList.forEach(item => {
const key = Object.keys(item)[0];
let attrs = item[key];
if (Array.isArray(item[key])) {
attrs = item[key].map(attr => {
try {
return JSON.parse(attr);
} catch {
return { attributeValueName: attr };
}
});
} else {
try {
attrs = [JSON.parse(item[key])];
} catch {
attrs = [{ attributeValueName: item[key] }];
}
}
attributeApplyList.push({
attributeId: key.replace('attr', ''),
attributeApplyValueList: attrs,
});
});
await this.setState(prev => ({ await this.setState(prev => ({
confirmLoading: true, confirmLoading: true,
createData: { createData: {
...@@ -419,8 +459,10 @@ class goodsManage extends Component { ...@@ -419,8 +459,10 @@ class goodsManage extends Component {
specs, specs,
character: values.character, character: values.character,
afterAddressId: values.afterAddressId, afterAddressId: values.afterAddressId,
attributeApplyList,
}, },
})); }));
console.log('this.state.createData :>> ', this.state.createData);
const data = initData.id const data = initData.id
? await editGoods(this.state.createData) ? await editGoods(this.state.createData)
: await addGoods(this.state.createData); : await addGoods(this.state.createData);
...@@ -488,6 +530,57 @@ class goodsManage extends Component { ...@@ -488,6 +530,57 @@ class goodsManage extends Component {
this.BatchSetting.formRef.current.resetFields(); this.BatchSetting.formRef.current.resetFields();
}; };
/**
* 获取下拉框类型
* supportCustomValue:是否支持自定义:1 是 0 否
* optionType:选项类型:1 单选 2 多选
*/
getMode = (supportCustomValue, optionType) => {
if (+supportCustomValue.code === 1) {
return 'tags';
}
if (+optionType.code === 2) {
return 'multiple';
}
return 'default';
};
getInitAttrValue = (id, supportCustomValue, optionType) => {
console.log('id :>> ', id, supportCustomValue.code, optionType.code);
const skuAttr = this.props.initData.productAttributeApplyList?.productAttributeApplyList || [];
const v = skuAttr.filter(item => id === item.productAttributeId);
if (v.length) {
const values = v[0].productAttributeApplyValueList.map(attr => {
if (+attr.attributeValueId) {
return JSON.stringify({
attributeValueId: attr.attributeValueId,
attributeValueName: attr.attributeValueName,
});
}
return attr.attributeValueName;
});
if (+supportCustomValue.code === 1 || +optionType.code === 2) {
return values;
}
if (v[0].productAttributeApplyValueList.length) {
const atvalue = v[0].productAttributeApplyValueList[0];
return JSON.stringify({
attributeValueId: atvalue.attributeValueId,
attributeValueName: atvalue.attributeValueName,
});
}
return '';
}
if (+supportCustomValue.code === 1) {
return [];
}
if (+optionType.code === 2) {
return [];
}
console.log('111 :>> ', 111);
return '';
};
validateToInputName = (rule, value, callback) => { validateToInputName = (rule, value, callback) => {
if (value.trim().length < 2) { if (value.trim().length < 2) {
callback(new Error('商品名称不可小于2个字符')); callback(new Error('商品名称不可小于2个字符'));
...@@ -528,6 +621,10 @@ class goodsManage extends Component { ...@@ -528,6 +621,10 @@ class goodsManage extends Component {
labelCol: { span: 2 }, labelCol: { span: 2 },
wrapperCol: { span: 22 }, wrapperCol: { span: 22 },
}; };
const formItemAttr = {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
const { const {
colorImg, colorImg,
productType, productType,
...@@ -538,7 +635,6 @@ class goodsManage extends Component { ...@@ -538,7 +635,6 @@ class goodsManage extends Component {
} = this.state; } = this.state;
const skuSpeFirstKeys = initData.firstSpecList || []; const skuSpeFirstKeys = initData.firstSpecList || [];
const skuSpeSecondKeys = initData.secondSpecList || []; const skuSpeSecondKeys = initData.secondSpecList || [];
const skuAttr = initData.productAttributeApplyList?.productAttributeApplyList || [];
const skuOldAttr = initData.productAttributeApplyList?.oldProductAttributeApplyList || []; const skuOldAttr = initData.productAttributeApplyList?.oldProductAttributeApplyList || [];
const treeDataArray = productType === 2 ? virtualTreeData : treeData; const treeDataArray = productType === 2 ? virtualTreeData : treeData;
const brandListArray = productType === 2 ? brandList : normalBrandList; const brandListArray = productType === 2 ? brandList : normalBrandList;
...@@ -549,11 +645,6 @@ class goodsManage extends Component { ...@@ -549,11 +645,6 @@ class goodsManage extends Component {
if (isEdit && !initData.editData[0]?.firstSpec && !initData.editData[0]?.secondSpec) { if (isEdit && !initData.editData[0]?.firstSpec && !initData.editData[0]?.secondSpec) {
colorKeys = colorKeys.length > 1 ? colorKeys.filter(item => item !== 'null') : colorKeys; colorKeys = colorKeys.length > 1 ? colorKeys.filter(item => item !== 'null') : colorKeys;
} }
const optionsWithDisabled = [
{ label: 'Apple', value: 'Apple' },
{ label: 'Pear', value: 'Pear' },
{ label: 'Orange', value: 'Orange', disabled: false },
];
return ( return (
<Modal <Modal
...@@ -741,25 +832,49 @@ class goodsManage extends Component { ...@@ -741,25 +832,49 @@ class goodsManage extends Component {
<Card className={styles.card} bordered={false}> <Card className={styles.card} bordered={false}>
<div className={styles.cardTitle}>商品属性</div> <div className={styles.cardTitle}>商品属性</div>
<Row> <Row>
{skuAttr.length > 0 && {this.state.categoryAttrs.length > 0 &&
skuAttr.map(k => ( this.state.categoryAttrs.map((k, i) => (
<FormItem label={k.name} required={false} key={k}> <Col span={12} key={k.id}>
{getFieldDecorator(`specs[${k}]`, { <FormItem label={k.name} {...formItemAttr} key={k.id}>
initialValue: this.state.initForm.second[k] || '', {getFieldDecorator(`attributeApplyList[${i}]['attr${k.id}']`, {
validateTrigger: ['onChange', 'onBlur'], initialValue:
rules: +k.required === 1 ? { required: true, message: '请选择' } : [], +k.supportCustomValue.code === 1 || +k.optionType.code === 2 ? [] : '', // this.getInitAttrValue(k.id, k.supportCustomValue, k.optionType), //
})( validateTrigger: ['onChange'],
<Select mode={this.getMode(k.supportCustomValue, k.optionType)}> rules:
{k.valueList && +k.required.code === 1
k.valueList.length && ? [
k.valueList.map(a => ( {
<Option key={a.id} value={a}> required: true,
{a.name} type:
</Option> +k.supportCustomValue.code === 1 || +k.optionType.code === 2
))} ? 'array'
</Select>, : 'string',
)} message: '请选择',
</FormItem> },
]
: [],
})(
<Select
mode={this.getMode(k.supportCustomValue, k.optionType)}
allowClear
>
{k.valueList &&
k.valueList.length &&
k.valueList.map(a => (
<Option
key={a.id}
value={JSON.stringify({
attributeValueId: a.id,
attributeValueName: a.name,
})}
>
{a.name}
</Option>
))}
</Select>,
)}
</FormItem>
</Col>
))} ))}
</Row> </Row>
<Row> <Row>
......
...@@ -3,16 +3,18 @@ import { Modal, Button } from 'antd'; ...@@ -3,16 +3,18 @@ import { Modal, Button } from 'antd';
import { apiQueryLastAuditRecord } from '../service'; import { apiQueryLastAuditRecord } from '../service';
const InfoAudit = props => { const InfoAudit = props => {
const [audit, setAudit] = useState({});
const getRecord = async () => { const getRecord = async () => {
console.log('333 :>> ', props.skuInfo.skuId); const res = await apiQueryLastAuditRecord(props.skuInfo.skuId);
// const res = await apiQueryLastAuditRecord(props.skuInfo.skuId); if (res && res.data) {
// console.log('res :>> ', res); console.log('res :>> ', res);
setAudit(res.data);
}
}; };
useEffect(() => { useEffect(() => {
console.log('1111 :>> ', 1111);
if (props.visible) { if (props.visible) {
console.log('222 :>> ', 222);
getRecord(); getRecord();
} }
}, [props.visible]); }, [props.visible]);
...@@ -30,9 +32,9 @@ const InfoAudit = props => { ...@@ -30,9 +32,9 @@ const InfoAudit = props => {
</Button>, </Button>,
]} ]}
> >
<p>审核状态:审核拒绝</p> <p>审核状态:{audit.statusDesc}</p>
<p>申请时间:</p> <p>申请时间:{audit.createdAt}</p>
<p>审核结果:</p> <p>审核结果:{audit.rejectReason}</p>
</Modal> </Modal>
); );
}; };
......
...@@ -43,14 +43,15 @@ export async function getBrandList() { ...@@ -43,14 +43,15 @@ export async function getBrandList() {
} }
// 获取类目关联属性 // 获取类目关联属性
export async function apiGetAttribute(params) { export async function apiGetAttribute(categoryId) {
const data = await request.get('/api/kdsp/category/template/ref/attribute', { const data = await request.get(
prefix: goodsApi, `/api/kdsp/category/template/ref/attribute/detail?categoryId=${categoryId}`,
params, {
}); prefix: goodsApi,
},
);
return data; return data;
} }
// 编辑--获取详情 // 编辑--获取详情
export async function spuDetail(params) { export async function spuDetail(params) {
return request.post('/product/api/merchant/detail', { return request.post('/product/api/merchant/detail', {
......
...@@ -3,7 +3,7 @@ import { Button, Badge, Switch, Modal } from 'antd'; ...@@ -3,7 +3,7 @@ import { Button, Badge, Switch, Modal } from 'antd';
import { ExclamationCircleOutlined } from '@ant-design/icons'; import { ExclamationCircleOutlined } from '@ant-design/icons';
import styles from './style.less'; import styles from './style.less';
import { resetTime } from '../../utils/utils'; import { resetTime } from '../../utils/utils';
import { apiChangeStateGoods } from './service'; import { apiChangeStateGoods, apiQueryLastAuditRecord } from './service';
const { confirm } = Modal; const { confirm } = Modal;
...@@ -189,9 +189,14 @@ export function column() { ...@@ -189,9 +189,14 @@ export function column() {
render: (_, row) => ( render: (_, row) => (
<div> <div>
<p>{row.state >= 5 ? '审核通过' : _}</p> <p>{row.state >= 5 ? '审核通过' : _}</p>
<div onClick={() => onShowAudit(row)}> <div>
{' '} {row.updateStateDesc ? (
{row.updateStateDesc ? <span>{row.updateStateDesc}</span> : '--'} <span onClick={() => onShowAudit(row)} className={styles.stateAuditTxt}>
{row.updateStateDesc}
</span>
) : (
'--'
)}
</div> </div>
</div> </div>
), ),
......
...@@ -115,3 +115,7 @@ ...@@ -115,3 +115,7 @@
font-weight: bold; font-weight: bold;
font-size: 18px; font-size: 18px;
} }
.stateAuditTxt {
color: #1890ff;
cursor: pointer;
}
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