Commit aeac15f4 authored by 杨鑫's avatar 杨鑫

Merge branch 'feature/commodity-properties' into 'master'

Feature/commodity properties

See merge request !62
parents 7eefd136 24e5ad8c
...@@ -14,5 +14,6 @@ module.exports = { ...@@ -14,5 +14,6 @@ module.exports = {
'@typescript-eslint/no-unused-vars': ['off'], '@typescript-eslint/no-unused-vars': ['off'],
'import/no-unresolved': 0, 'import/no-unresolved': 0,
'import/extensions': 0, 'import/extensions': 0,
'no-unused-expressions': ['error', { allowShortCircuit: true }],
}, },
}; };
const isProduction = process.env.NODE_ENV === 'production'; const isProduction = process.env.NODE_ENV === 'production';
const isPre = process.env.PRE_ENV === 'pre'; const isPre = process.env.PRE_ENV === 'pre';
const environment = 'xyqb';
const envAPi = { const envAPi = {
api: 'https://security-xyqb.liangkebang.net', //'https://security-xyqb.liangkebang.net', api: `https://security-${environment}.liangkebang.net`,
kdspOpApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspOpApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
kdspApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
goodsApi: 'https://sc-merchant-api-xyqb.liangkebang.net', goodsApi: `https://sc-merchant-api-${environment}.liangkebang.net`,
// kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net', querysApi: `https://sc-merchant-api-${environment}.liangkebang.net/admin/merchant/sc-settlement`,
// kdspApi: 'https://sc-op-api-xyqb.liangkebang.net', prologueDomain: `https://mall-${environment}.liangkebang.net`,
// goodsApi: 'https://sc-op-api-xyqb.liangkebang.net', qiniuHost: `https://kdspstatic.q-gp.com/`,
querysApi: 'https://sc-merchant-api-sc.liangkebang.net', opapiHost: `https://yxm-gateway-${environment}.liangkebang.net`,
// goodsApi: '//192.168.188.111:7000',
prologueDomain: 'https://mall-sc.liangkebang.net',
// qiniuHost: 'https://appsync.lkbang.net',
qiniuHost: 'https://kdspstatic.q-gp.com/',
opapiHost: 'https://opapi-sc.liangkebang.net',
}; };
const prodApi = { const prodApi = {
...@@ -26,7 +21,7 @@ const prodApi = { ...@@ -26,7 +21,7 @@ const prodApi = {
goodsApi: 'https://sc-merchant-api.q-gp.com', // 线上环境打包域名 goodsApi: 'https://sc-merchant-api.q-gp.com', // 线上环境打包域名
qiniuHost: 'https://kdspstatic.q-gp.com/', qiniuHost: 'https://kdspstatic.q-gp.com/',
// talos 后面要下线 // talos 后面要下线
opapiHost: '//talos.xyqb.com', opapiHost: '//gw.yxmie.com',
// opapiHost: 'https://opapi.q-gp.com', // opapiHost: 'https://opapi.q-gp.com',
// querysApi: 'https://sc-settlement-api.q-gp.com', // querysApi: 'https://sc-settlement-api.q-gp.com',
querysApi: 'https://sc-merchant-api.q-gp.com/admin/merchant/sc-settlement', querysApi: 'https://sc-merchant-api.q-gp.com/admin/merchant/sc-settlement',
......
This diff is collapsed.
import React, { useState, useEffect } from 'react';
import { Modal, Button } from 'antd';
import { apiQueryLastAuditRecord } from '../service';
const InfoAudit = props => {
const [audit, setAudit] = useState({});
const getRecord = async () => {
const res = await apiQueryLastAuditRecord(props.skuInfo.skuId);
if (res && res.data) {
console.log('res :>> ', res);
setAudit(res.data);
}
};
const getContent = () => {
const obj = {
1: '-',
2: '审核通过',
3: `审核拒绝,${audit.rejectReason}`,
};
if (audit) {
return obj[audit.status] || '';
}
return '';
};
useEffect(() => {
if (props.visible) {
getRecord();
}
}, [props.visible]);
return (
<Modal
title="商品信息变更审核"
visible={props.visible}
closable={false}
footer={[
audit.status === 3 &&
props.canEditable &&
(props.skuInfo.state === 4 ||
(props.skuInfo.state >= 5 && props.skuInfo.updateState !== 1)) && (
<Button key="back" type="primary" onClick={() => props.onEdit()}>
再次编辑
</Button>
),
<Button key="close" onClick={() => props.onCancel()}>
关闭
</Button>,
]}
>
<p>审核状态:{audit.statusDesc}</p>
<p>申请时间:{audit.createdAt}</p>
<p>审核结果:{getContent()}</p>
</Modal>
);
};
export default InfoAudit;
import { Form } from '@ant-design/compatible'; import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css'; import '@ant-design/compatible/assets/index.css';
import { Card, Pagination, Table, notification, Drawer, Spin, Button } from 'antd'; import { Card, Pagination, Table, notification, Drawer, Spin, Button, Modal } from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva'; import { connect } from 'dva';
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import { da } from 'date-fns/locale';
import styles from './style.less'; import styles from './style.less';
import LocalStroage from '@/utils/localStorage'; import LocalStroage from '@/utils/localStorage';
import configApi from '../../../config/env.config'; import configApi from '../../../config/env.config';
...@@ -27,6 +26,7 @@ import { column, JDSHOPID, ProcessEditData } from './staticdata'; ...@@ -27,6 +26,7 @@ import { column, JDSHOPID, ProcessEditData } from './staticdata';
import SearchForm from './SearchForm'; import SearchForm from './SearchForm';
import TempleatModal from './TempleatModal'; import TempleatModal from './TempleatModal';
import ServiceGoods from '../ServiceGoods'; import ServiceGoods from '../ServiceGoods';
import InfoAudit from './createModal/infoAudit';
import { GOOD_MANAGE } from '@/../config/permission.config'; import { GOOD_MANAGE } from '@/../config/permission.config';
...@@ -58,6 +58,8 @@ class goodsManage extends Component { ...@@ -58,6 +58,8 @@ class goodsManage extends Component {
serviceVisble: false, serviceVisble: false,
serviceData: {}, serviceData: {},
visibleAuditModal: false,
auditRow: {}, // 查看审核信息使用
}; };
currentLog = null; currentLog = null;
...@@ -495,18 +497,20 @@ class goodsManage extends Component { ...@@ -495,18 +497,20 @@ class goodsManage extends Component {
title="商品预览" title="商品预览"
></iframe> ></iframe>
</Drawer> </Drawer>
<CreateModal {this.state.createVisible && (
initData={this.state.initData} <CreateModal
visible={this.state.createVisible} initData={this.state.initData}
onCancel={() => { visible={this.state.createVisible}
this.setState({ createVisible: false, initData: {} }); onCancel={() => {
}} this.setState({ createVisible: false, initData: {} });
query={() => this.handleSearch()} }}
shopList={this.filterShopList(this.shopList, Object.keys(this.state.initData).length)} query={() => this.handleSearch()}
treeData={this.state.treeData} shopList={this.filterShopList(this.shopList, Object.keys(this.state.initData).length)}
virtualTreeData={this.state.virtualTreeData} treeData={this.state.treeData}
specListData={this.state.specListData} virtualTreeData={this.state.virtualTreeData}
></CreateModal> specListData={this.state.specListData}
></CreateModal>
)}
<UpdateStock <UpdateStock
visible={this.state.updateStockVisible} visible={this.state.updateStockVisible}
...@@ -537,6 +541,22 @@ class goodsManage extends Component { ...@@ -537,6 +541,22 @@ class goodsManage extends Component {
specListData={this.state.specListData} specListData={this.state.specListData}
/> />
</Spin> </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);
}
}}
/>
</PageHeaderWrapper> </PageHeaderWrapper>
); );
} }
......
...@@ -9,6 +9,10 @@ const headers = { ...@@ -9,6 +9,10 @@ const headers = {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}; };
/**
* 商品列表
* yapi: http://yapi.quantgroups.com/project/389/interface/api/23814
*/
export async function searchList(params) { export async function searchList(params) {
return request.post('/product/api/merchant/page', { return request.post('/product/api/merchant/page', {
prefix: goodsApi, prefix: goodsApi,
...@@ -42,6 +46,16 @@ export async function getBrandList() { ...@@ -42,6 +46,16 @@ export async function getBrandList() {
}); });
} }
// 获取类目关联属性
export async function apiGetAttribute(categoryId) {
const data = await request.get(
`/api/kdsp/category/template/ref/attribute/detail?categoryId=${categoryId}`,
{
prefix: goodsApi,
},
);
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', {
...@@ -73,6 +87,15 @@ export async function categoryList() { ...@@ -73,6 +87,15 @@ export async function categoryList() {
prefix: goodsApi, prefix: goodsApi,
}); });
} }
/**
* 商品分类
* type 商品类型:1-实物类,2-虚拟类,4-服务类
* */
export async function apiCategoryListType(type) {
return request.get(`/product/category/getByProductType/${type}`, {
prefix: goodsApi,
});
}
// 批量修改 // 批量修改
export async function uploadFile(file) { export async function uploadFile(file) {
...@@ -240,3 +263,9 @@ export const apiChangeStateGoods = async params => { ...@@ -240,3 +263,9 @@ export const apiChangeStateGoods = async params => {
}); });
return data; return data;
}; };
// 查询sku最后一条审核记录
export const apiQueryLastAuditRecord = skuId =>
request.get(`/api/kdsp/sku/last/audit/record?skuId=${skuId}`, {
prefix: goodsApi,
});
...@@ -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;
...@@ -50,6 +50,12 @@ export function column() { ...@@ -50,6 +50,12 @@ export function column() {
}, },
}); });
}; };
const onShowAudit = row => {
this.setState({
auditRow: row,
visibleAuditModal: true,
});
};
return [ return [
{ {
...@@ -183,7 +189,15 @@ export function column() { ...@@ -183,7 +189,15 @@ export function column() {
render: (_, row) => ( render: (_, row) => (
<div> <div>
<p>{row.state >= 5 ? '审核通过' : _}</p> <p>{row.state >= 5 ? '审核通过' : _}</p>
<p>{row.updateStateDesc || '_ _'}</p> <div>
{row.updateState ? (
<Button onClick={() => onShowAudit(row)} type="link">
{row.updateStateDesc}
</Button>
) : (
'--'
)}
</div>
</div> </div>
), ),
}, },
......
...@@ -110,3 +110,19 @@ ...@@ -110,3 +110,19 @@
color: #d9363e; color: #d9363e;
line-height: 1; line-height: 1;
} }
.cardTitle {
padding: 15px;
font-weight: bold;
font-size: 18px;
}
.stateAuditTxt {
color: #1890ff;
cursor: pointer;
}
.attrbox {
max-height: 384px;
overflow: hidden;
}
.attrboxMore {
max-height: max-content;
}
...@@ -46,19 +46,21 @@ class PicturesWall extends React.Component { ...@@ -46,19 +46,21 @@ class PicturesWall extends React.Component {
}; };
customRequest = ({ file, onError, onSuccess }) => { customRequest = ({ file, onError, onSuccess }) => {
let filename = '';
let suffix = '';
if (file.name) { if (file.name) {
const lastFile = file.name.split('.'); const index = file.name.lastIndexOf('.');
const index = lastFile.length - 1; filename = file.name.substr(0, index);
suffix = file.name.substr(index + 1, file.name.length - 1);
const types = ['pdf', 'doc', 'docx', 'zip', 'rar', 'png', 'jpeg']; const types = ['pdf', 'doc', 'docx', 'zip', 'rar', 'png', 'jpeg'];
if (!types.includes(lastFile[index])) { if (!types.includes(suffix)) {
message.error('文件格式错误!'); message.error('文件格式错误!');
return; return;
} }
} }
const vm = this; const vm = this;
const name = file.name + file.uid;
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
const data = file.name + new Date().getTime(); const data = `${filename}-${new Date().getTime()}.${suffix}`;
const observable = qiniu.upload(file, data, token); const observable = qiniu.upload(file, data, token);
const observer = { const observer = {
next() { next() {
......
...@@ -172,7 +172,6 @@ const EditFormTable = forwardRef((props, ref) => { ...@@ -172,7 +172,6 @@ const EditFormTable = forwardRef((props, ref) => {
return ( return (
<> <>
<Form form={form} scrollToFirstError component={false}> <Form form={form} scrollToFirstError component={false}>
{/* <Button onClick={onCheck}>测试</Button> */}
<EditableContext.Provider value={form}> <EditableContext.Provider value={form}>
<Table <Table
scroll={{ y: 300, x: 1000 }} scroll={{ y: 300, x: 1000 }}
......
...@@ -24,10 +24,24 @@ const FormRuleSetting = forwardRef((props, ref) => { ...@@ -24,10 +24,24 @@ const FormRuleSetting = forwardRef((props, ref) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const customer = useContext(ServiceContext); const customer = useContext(ServiceContext);
// 判断是否有禁用的店铺 禁用店铺不显示
const getIsInShops = arr => {
const list = [];
arr.forEach(item => {
supplierIdList.some(s => +s.id === +item) && list.push(item);
});
return list;
};
useEffect(() => { useEffect(() => {
if (customer.isEdit) { if (customer.isEdit) {
if (!editData) return; if (!editData) return;
form.setFieldsValue(editData); const goodInfo = Object.assign({}, editData);
if (goodInfo.shopIds) {
const shopIds = getIsInShops(editData.shopIds);
goodInfo.shopIds = shopIds;
}
form.setFieldsValue(goodInfo);
} }
}, [customer.isEdit, editData]); }, [customer.isEdit, editData]);
...@@ -98,7 +112,14 @@ const FormRuleSetting = forwardRef((props, ref) => { ...@@ -98,7 +112,14 @@ const FormRuleSetting = forwardRef((props, ref) => {
label="适用门店" label="适用门店"
rules={[{ required: true, message: '请选择适用门店!', type: 'array' }]} rules={[{ required: true, message: '请选择适用门店!', type: 'array' }]}
> >
<Select mode="multiple" placeholder="请选择适用门店"> <Select
mode="multiple"
placeholder="请选择适用门店"
showSearch
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{(supplierIdList || []).map(item => ( {(supplierIdList || []).map(item => (
<Option value={+item.id} key={item.id}> <Option value={+item.id} key={item.id}>
{item.name} {item.name}
......
...@@ -142,6 +142,7 @@ const FormRuleVPictures = forwardRef((props, ref) => { ...@@ -142,6 +142,7 @@ const FormRuleVPictures = forwardRef((props, ref) => {
> >
<UploadImage <UploadImage
disabled={customer.isService} disabled={customer.isService}
multiple={false}
name="commonImageList" name="commonImageList"
limit={imgConfig.commonImageList.limit} limit={imgConfig.commonImageList.limit}
pictures={commonImageList} pictures={commonImageList}
......
...@@ -192,21 +192,25 @@ const UploadImage = forwardRef((props, ref) => { ...@@ -192,21 +192,25 @@ const UploadImage = forwardRef((props, ref) => {
</ReactSortable> </ReactSortable>
)} )}
</div> </div>
<Upload {limit !== null && fileList.length >= limit ? (
{...uploadParams} ''
disabled={Boolean(disabled)} ) : (
multiple={multiple} <Upload
name={name} {...uploadParams}
customRequest={() => {}} disabled={Boolean(disabled)}
listType="picture-card" multiple={multiple}
beforeUpload={defaultBeforeUpload} name={name}
fileList={fileList} customRequest={() => {}}
onPreview={handlePreview} listType="picture-card"
onRemove={handleRemove} beforeUpload={defaultBeforeUpload}
showUploadList={false} fileList={fileList}
> onPreview={handlePreview}
{limit !== null && fileList.length >= limit ? null : UploadButton} onRemove={handleRemove}
</Upload> showUploadList={false}
>
{UploadButton}
</Upload>
)}
<Modal visible={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel}> <Modal visible={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel}>
<img alt="example" style={{ width: '100%' }} src={previewImage} /> <img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal> </Modal>
......
...@@ -236,7 +236,7 @@ export const StaticColumns = customer => [ ...@@ -236,7 +236,7 @@ export const StaticColumns = customer => [
min: 0, min: 0,
}, },
roleRules: { required: true }, roleRules: { required: true },
disabeldRender: () => customer.isService, disabeldRender: v => v.id && customer.isService,
}, },
{ {
title: '库存预警', title: '库存预警',
......
...@@ -4,6 +4,9 @@ import config from '../../config/env.config'; ...@@ -4,6 +4,9 @@ import config from '../../config/env.config';
export async function qiniuToken() { export async function qiniuToken() {
const data = await request.get('/api/kdsp/common/upload/token', { const data = await request.get('/api/kdsp/common/upload/token', {
prefix: config.opapiHost, prefix: config.opapiHost,
headers: {
'qg-tenant-id': 560761,
},
}); });
return data?.data?.token; return data?.data?.token;
} }
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