Commit 4e91c9ca authored by GuanHua's avatar GuanHua
parents 077f50cd 7eee52fa
......@@ -2,7 +2,7 @@
* @Author: LeeJiancong
* @Date: 2020-07-13 14:08:50
* @LastEditors: LeeJiancong
* @LastEditTime: 2020-07-18 18:56:08
* @LastEditTime: 2020-08-19 15:39:49
*/
import CommodityRoute from './commodityRoute' // 商品能力路由
import MemberRoute from './memberRoute' // 会员能力路由
......@@ -10,8 +10,9 @@ import ShopRoute from './shopRoute' // 店铺能力路由
import ChannelRoute from './channelRoute' // 渠道能力路由
import TranactionRoute from './tranactionRoute' // 交易能力路由
import LogisticsRoute from './logisticsRoutes' // 物流能力路由
import PayandSettleRoute from './payandSettle' //支付与结算
const routes = [CommodityRoute, MemberRoute, ShopRoute, ChannelRoute, TranactionRoute, LogisticsRoute]
const routes = [CommodityRoute, MemberRoute, ShopRoute, ChannelRoute, TranactionRoute,PayandSettleRoute ,LogisticsRoute]
const memberCenterRoute = {
path: '/memberCenter',
......
/*
* @Author: LeeJiancong
* @Date: 2020-07-13 14:36:02
* @LastEditors: LeeJiancong
* @Copyright: 1549414730@qq.com
* @LastEditTime: 2020-08-19 15:34:24
*/
/*
* @Author: Ljc
* @Date: 2020-07-10 16:15:28
* @Last Modified by: ljc
......
/*
* @Author: LeeJiancong
* @Date: 2020-08-19 15:33:27
* @LastEditors: LeeJiancong
* @Copyright: 1549414730@qq.com
* @LastEditTime: 2020-08-20 10:22:11
*/
const payandSettleRoute = {
path:'/memberCenter/payandSettle',
name:'payandSettle',
icon:'smile',
routes:[
{
path:'/memberCenter/payandSettle/paySetting',
name:'paySetting',
key:'paySetting',
routes:[
{
path:'/memberCenter/payandSettle/paySetting/payParamsSetting',
name:'payParamsSetting',
key:'payParamsSetting',
component:'@/pages/payandSettle/paySetting'
}
]
}
]
}
export default payandSettleRoute
\ No newline at end of file
/*
* @Author: LeeJiancong
* @Date: 2020-07-17 18:01:43
* @LastEditors: LeeJiancong
* @Copyright: 1549414730@qq.com
* @LastEditTime: 2020-08-19 17:24:16
*/
/**
* 用于在项目开始前获取所有的配置
* 在项目开始前运行`yarn scripts:build`
......@@ -44,6 +51,14 @@ const serviceConfig = {
// // }
// }
},
//初始化会员支付策略配置
payConfig:{
paymemberConfig:{
url:'/pay/member/pay/config',
method: 'get'
}
}
}
......@@ -68,13 +83,15 @@ async function batchAxiosHttps() {
// }
// serverFn(asyncHttpQueue)
for (const item in serviceConfig) {
for (const subItem in serviceConfig[item]) {
try {
const data = await axios(serviceConfig[item][subItem])
asyncHttpQueue[item][subItem] = data.data.data
} catch(err) {
console.log(serviceConfig[item][subItem].url)
console.log(err.response.data)
if(JSON.stringify(item) !== '{}'){
for (const subItem in serviceConfig[item]) {
try {
const data = await axios(serviceConfig[item][subItem])
asyncHttpQueue[item][subItem] = data.data.data
} catch(err) {
console.log(serviceConfig[item][subItem].url)
console.log(err.response.data)
}
}
}
}
......
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { Input, Space, Select, Button } from 'antd';
import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons';
import { useFieldState, FormPath, FormEffectHooks } from '@formily/antd';
import { useFieldState, FormPath, FormEffectHooks, useFormEffects } from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { PublicApi } from '@/services/api';
/**
* 筛选项 搜索和远程数据结合的select
* search的值暂存至schema的props下的searchValue
* option数据暂存至schema的props下的dataOption
*/
const { Option } = Select
// export interface SearchProps {
......@@ -14,35 +20,32 @@ const { Option } = Select
// }
const CustomInputSearch = props => {
console.log(props);
const justifyAlign = props.props['x-component-props'].align || 'flex-end';
const [brandData, setBrandData] = useState<any>([])
const [brandValue, setBrandValue] = useState(undefined)
const handleBrandSearch = (value: any) => { // end value
console.log(value, '搜索值')
if (value) {
PublicApi.getProductSelectGetSelectBrand({ name: value }).then(res => {
if (res.code === 1000)
setBrandData(res.data)
})
} else {
setBrandData([])
}
}
console.log(props, 'props')
const { form } = props
const justifyAlign = props.props['x-component-props'].align || 'flex-end'
const option = props.props['x-component-props'].dataOption
const [dataOption, setDataOption] = useState<any>([])
// 只能在组件中获取对应的值
useEffect(() => {
setDataOption(option)
}, [option])
const handleValueSearch = (value: any) => {
form.setFieldState(props.props.key, state => {
state.props["x-component-props"].searchValue = value // search的值暂存至schema的props下的searchValue
})
}
return (
<Space size={20} style={{ justifyContent: justifyAlign, width: '100%' }}>
<Select
// value={brandValue}
onSearch={value => handleBrandSearch(value)}
onSearch={value => handleValueSearch(value)}
onChange={v => props.mutators.change(v)}
value={props.value}
{...props.props['x-component-props']}
>
{brandData.map(d => <Option value={d.id} key={d.id}>{d.name}</Option>)}
{dataOption.map(d => <Option value={d.id} key={d.id}>{d.name}</Option>)}
</Select>
</Space>
);
......
import React from 'react';
import { Table } from 'antd';
import classNames from 'classnames';
import { TableProps, TablePaginationConfig, ColumnType } from 'antd/lib/table';
import { PaginationProps } from 'antd/lib/pagination';
import styles from './index.less';
export interface StandardTableProps extends TableProps<any> {
pagination: TablePaginationConfig;
onPaginationChange?: (page: number, size: number) => void;
};
export default class StandardTable extends React.PureComponent<StandardTableProps> {
state = {
page: 1,
size: 10,
};
handlePaginationChange = (page: number, size: number) => {
const { pagination = {}, onPaginationChange } = this.props;
const { current, pageSize } = pagination;
// 内部自己维护 page、size, 单独控制当前页 或 当前页数
if (!('current' in pagination)) {
this.setState({ page: current });
}
if (!('pageSize' in pagination)) {
this.setState({ size: pageSize });
}
if (onPaginationChange) {
onPaginationChange(page, size);
}
};
render() {
const { page, size } = this.state;
const {
columns,
dataSource,
rowKey = 'id',
pagination = {},
loading,
className,
onPaginationChange,
...restProps
} = this.props;
const newPagination: any = pagination ? {
current: page,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
onChange: this.handlePaginationChange,
onShowSizeChange: this.handlePaginationChange,
size: 'small',
showTotal: () => `共 ${pagination.total || 0} 条`,
...pagination,
} : false;
return (
<div className={classNames(className)}>
<Table
rowKey={rowKey}
columns={columns}
dataSource={dataSource}
loading={loading}
pagination={newPagination}
{...restProps}
/>
</div>
)
}
}
\ No newline at end of file
......@@ -20,4 +20,9 @@ export const Environment_Status = {
}
// 1是阿里云oss服务器, 2是本地文件服务器
export const UPLOAD_TYPE = isDev ? 2 : 1
\ No newline at end of file
export const UPLOAD_TYPE = isDev ? 2 : 1
// 会员规则类型
export const VIP_RULE_TRANSACTION = 1; // 交易
export const VIP_RULE_LOGIN = 2; // 登录
export const VIP_RULE_COMMENT = 3; // 评论
export interface MemberType {
id: number;
typeName: string;
}
export interface BusinessType {
id: number;
typeName: string;
}
export interface UseType {
memberType: MemberType[];
businessType: BusinessType[];
}
export interface UserRegister {
useType: UseType;
}
export interface ShopInfo {
id: number;
name: string;
type: number;
environment: number;
logoUrl: string;
describe: string;
state: number;
url: string;
}
export interface Web {
shopInfo: ShopInfo[];
}
export interface CountryList {
name: string;
key: string;
icon: string;
}
export interface Global {
siteId: number;
siteUrl: string;
logo: string;
countryList: CountryList[];
}
export interface RootObject {
userRegister: UserRegister;
web: Web;
global: Global;
}
\ No newline at end of file
......@@ -239,4 +239,28 @@ h6 {
margin-right: 0;
}
}
}
// 可编辑表格项公用样式
.editable-cell {
position: relative;
}
.editable-cell-value-wrap {
padding: 5px 12px;
min-height: 32px;
cursor: pointer;
}
.editable-row:hover
.editable-cell-value-wrap {
border: 1px solid #d9d9d9;
border-radius: 4px;
padding: 4px 11px;
}
.editable-row .ant-form-explain {
position: absolute;
font-size: 12px;
margin-top: -4px;
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: LeeJiancong
* @Date: 2020-07-13 14:08:50
* @LastEditors: LeeJiancong
* @LastEditTime: 2020-07-28 11:31:13
* @LastEditTime: 2020-08-20 10:22:52
*/
export default {
......@@ -116,4 +116,8 @@ export default {
'menu.logisticsAbility.logisticsResult.orderResultSearchList': '物流单查询',
'menu.logisticsAbility.logisticsResult.orderResultDeatil': '物流单详情',
'menu.logisticsAbility.logisticsResult.toOrderComfirmList': '待确认物流单',
'menu.payandSettle': '支付',
'menu.payandSettle.paySetting': '支付方式管理',
'menu.payandSettle.paySetting.payParamsSetting': '会员支付参数配置',
};
\ No newline at end of file
......@@ -148,26 +148,7 @@ const CategoryAttributes: React.FC<{}> = () => {
align: 'center',
dataIndex: 'isEnable',
key: 'isEnable',
render: (text: any, record: any) => {
let component: ReactNode = null
component = (
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => confirm(record)}
onCancel={cancel}
okText="是"
cancelText="否"
>
<Button
type="link"
style={text ? { color: '#00B37A' } : { color: 'red' }}
>
{text ? <>有效 <PlayCircleOutlined /></> : <>无效 <PauseCircleOutlined /></>}
</Button>
</Popconfirm>
)
return component
}
render: (text: any, record: any) => text ? '有效' : '无效'
},
{
title: '操作',
......@@ -261,7 +242,8 @@ const CategoryAttributes: React.FC<{}> = () => {
linkTableRowData.forEach((item, index) => {
linkArray.push(item.id)
})
console.log(linkArray)
// console.log(linkArray, goodsRowCtl)
goodsRowCtl.setSelectedRowKeys(linkArray)
setSelectedTableRowKeys(linkArray)
}
......
......@@ -36,7 +36,8 @@ const AddProducts: React.FC<{}> = (props) => {
setProductName,
setAttributeLists,
clearData,
setProductInfoByEdit
setProductInfoByEdit,
isAllAttributePic
} = ProductStore
useEffect(()=>{
......@@ -69,7 +70,6 @@ const AddProducts: React.FC<{}> = (props) => {
await __.current.validateFields()
)
})
// console.log(data,'data')
Promise.all(data).then((values) => {
// 提交的数据进行处理
// console.log(values, productSelectAttribute, productAttributeAndImageParams, '所有数据')
......@@ -77,25 +77,30 @@ const AddProducts: React.FC<{}> = (props) => {
delete _itme.attributeName
delete _itme.isPrice
})
if(productAttributeAndImageParams.length>0){
productAttributeAndImageParams.map(_item => {
if(_item.goodsCustomerAttributeList.length>0){
_item.goodsCustomerAttributeList.map(__item => {
delete __item.customerAttributeName
__item.customerAttributeValueId = __item.id
})
}
if(_item.commodityPic.length>0){
_item.commodityPic = _item.commodityPic.map(__item => {
return __item?.response?.data || __item?.url // 编辑情况下兼顾手动添加图片列表属性
})
}else{
return message.error("每项请至少上传一张商品图片!")
}
})
}
else{
return message.error("每项请至少上传一张商品图片!")
try{
if(productAttributeAndImageParams.length>0){
console.log(productAttributeAndImageParams,'____')
productAttributeAndImageParams.map(_item => {
if(_item.goodsCustomerAttributeList.length>0){
_item.goodsCustomerAttributeList.map(__item => {
delete __item.customerAttributeName
__item.customerAttributeValueId = __item.id
})
}
if(_item.commodityPic.length>0){
_item.commodityPic = _item.commodityPic.map(__item => {
return __item?.response?.data || __item?.url // 编辑情况下兼顾手动添加图片列表属性
})
}else{
throw new Error('每项请至少上传一张商品图片!')
}
})
}
else{
throw new Error('每项请至少上传一张商品图片!')
}
}catch(e){
return e
}
let _bacsicForm = {...values[0]}
_bacsicForm.customerCategoryId = _bacsicForm.customerCategoryId[_bacsicForm.customerCategoryId.length-1]
......@@ -106,26 +111,30 @@ const AddProducts: React.FC<{}> = (props) => {
...values[4],
commodityAttributeList: productSelectAttribute,
unitPriceAndPicList: productAttributeAndImageParams,
commodityRemark: productDescription
commodityRemark: productDescription,
isAllAttributePic: isAllAttributePic,
}
_params.minOrder = Number(_params.minOrder)
_params.logistics.weight = Number(_params.logistics.weight)
// 处理地址
let _commodityAreaList:any = []
// console.log(_params, '_params')
_params.commodityAreaList.length > 0 && _params.commodityAreaList.map(_itme => {
if(_itme){
let _temp: any = {}
let pobj = areaOption.filter(_=>_.code===_itme[0])[0]
let cobj = pobj.areaResponses.filter(__=>__.code===_itme[1])[0]
_temp.provinceCode = pobj.code
_temp.provinceName = pobj.name,
_temp.cityCode = cobj.code,
_temp.cityName = cobj.name,
_temp.provinceCode = pobj?.code || null
_temp.provinceName = pobj?.name || null
_temp.cityCode = cobj?.code || null
_temp.cityName = cobj?.name || null
// 增加不限市区字段
cobj?.code ? _temp.isAllCity = false : _temp.isAllCity = true
_commodityAreaList.push(_temp)
// console.log(_itme, _temp, '地址的每一项')
}
})
// 增加不限区域字段
_commodityAreaList.length > 0 ? _params.isAllArea = false : _params.isAllArea = true
_params.commodityAreaList = _commodityAreaList
const { id } = history.location.query
_params.id = id ? id : null
......@@ -133,17 +142,20 @@ const AddProducts: React.FC<{}> = (props) => {
PublicApi.postProductCommoditySaveOrUpdateCommodity(_params).then(res => {
if(res.code === 1000){
setIsEnableCheck(false)
//@ts-ignore
setReponseId(res.data)
history.goBack()
}
})
}).then( e => {
console.log(e, 'e')
if(e)
message.error(e.message)
}).catch(error => {
message.error("请完善表单必填项!")
console.log(error, '_error')
})
message.error(error.message)
})
}catch(e){
message.error(e.message)
console.log(e,'error')
}
}
......@@ -189,7 +201,7 @@ const AddProducts: React.FC<{}> = (props) => {
onRef={(refs)=>setFormRefs([...formRefs, refs])}
/>
</TabPane>
<TabPane tab="商品图片" key="5" style={{ border: '1px solid rgba(223,225,230,1)' }}>
<TabPane tab="商品图片" key="5">
<ProductImageForm />
</TabPane>
<TabPane tab="商品描述" key="6">
......
import React, { useState, useEffect, useRef } from 'react'
import { history } from 'umi'
import { Form, Select, Radio, Input, Checkbox } from 'antd'
import { Form, Select, Radio, Input, Checkbox, InputNumber } from 'antd'
import { PublicApi } from '@/services/api'
import { GetLogisticsSelectListCompanyResponse, GetLogisticsSelectListShipperAddressResponse, GetLogisticsSelectListFreightTemplateResponse } from '@/services'
import { store } from '@/store'
......@@ -112,19 +112,22 @@ const LogisticsForm: React.FC<Iprops> = (props) => {
</Radio.Group>
</Form.Item>
<Form.Item
name="weight"
label="重量"
rules={[
{
required: true,
type: 'number',
message: '请填入重量',
min: 0,
transform: (value) => Number(value)
},
]}
style={{position: 'relative'}}
>
<Input suffix="KG" placeholder="请输入重量" />
<Form.Item
name="weight"
rules={[
{
required: true,
message: '请正确输入重量',
}
]}
noStyle
>
<InputNumber min={0} style={{width:'100%'}} placeholder="请输入重量" />
</Form.Item>
<span style={{position:'absolute', right:5, top:5, opacity: 0.6}}>KG</span>
</Form.Item></>
}
{
......
......@@ -56,7 +56,7 @@ const ProductAttributeForm: React.FC<Iprops> = (props) => {
* @param {Number, Array, e} value type为1:数字id,type为2:数组id,type为3:事件对象
* @param {Object} attrItem 属性数据对象
*/
const onChange = (value, attrItem) => { // 编辑情况下 这里只生成一个 关联表格会有问题
const onChange = (value, attrItem) => {
let params = { customerAttributeId: attrItem.id, attributeName: attrItem.name, isPrice: attrItem.isPrice, customerAttributeValueList: [] }
console.log(params, 'params')
if(attrItem.type!==3){
......@@ -103,12 +103,12 @@ const ProductAttributeForm: React.FC<Iprops> = (props) => {
/* 编辑情况下,利用商品信息中的属性值转换为结果参数,用于后续表格生成 */
const constructProductSelectAttribute = () => {
let _selectAttributeByEdit = productInfoByEdit.commodityAttributeList.map((item, index) => {
// console.log(item,'__edit__',attributeLists[index])
console.log(item,'__edit__',attributeLists[index])
return {
attributeName: item.customerAttribute.name,
customerAttributeId: item.customerAttribute.id,
customerAttributeValueList: item.customerAttributeValueList,
isPrice: attributeLists.filter(_item => _item.name === item.customerAttribute.name)[0].isPrice
isPrice: attributeLists.filter(_item => _item.name === item.customerAttribute.name)[0]?.isPrice
}
})
console.log(_selectAttributeByEdit, '__selectAttributeByEdit__', attributeLists)
......@@ -130,7 +130,7 @@ const ProductAttributeForm: React.FC<Iprops> = (props) => {
}]}
>
<Select
placeholder="请选择面料"
placeholder="请选择"
allowClear
onChange={(v)=>onChange(v, attrItem)}
>
......
import React, { useState, useEffect } from 'react'
import {history} from 'umi'
import { Button, Form, Select, Checkbox, message, Input, Table, Modal, Row, Col, Alert, Upload } from 'antd'
import { Button, Form, Select, Checkbox, message, Input, Table, Modal, Row, Col, Alert, Upload, Radio } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import CustomTabs, { ItemPane } from '@/components/CustomTabs'
import styles from './index.less'
......@@ -43,23 +43,19 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
const [previewVisible, setPreviewVisible] = useState(false)
const [previewImage, setPreviewImage] = useState('')
const [previewTitle, setPreviewTitle] = useState('')
const [setImageType, setSetImageType] = useState<boolean>(true)
const { ProductStore } = store
const { priceAttributeParams, productInfoByEdit, setProductAttributeAndImageParams } = ProductStore
const { priceAttributeParams, productInfoByEdit, setProductAttributeAndImageParams, setIsAllAttributePic } = ProductStore
/* 给数据添加图片字段 */
useEffect(()=>{
// console.log('!!!', priceAttributeParams)
// let _priceAttributeParams = priceAttributeParams.map(_item=>{
// let _obj = {..._item}
// _obj.commodityPic = [] // 编辑情况下 经行处理
// return _obj
// })
let _priceAttributeParams: any = []
if(productInfoByEdit?.id){ // id判断是否新增还是编辑
setSetImageType(productInfoByEdit.isAllAttributePic || true)
let _commodityPicList = productInfoByEdit.unitPriceAndPicList.map(_ => _.commodityPic)
_priceAttributeParams = priceAttributeParams.map((_item, _index) => {
// console.log(_commodityPicList[_index]) // 为图片字符串数组手动添加 uid 和 status
// 为图片字符串数组手动添加 uid 和 status
let _commodityPicItem = Array.isArray(_commodityPicList[_index]) ? _commodityPicList[_index].map((__ele, __i) => {
return {
uid: __i * -1,
......@@ -81,14 +77,22 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
// console.log('???', _priceAttributeParams)
if(_priceAttributeParams?.length>0 && _priceAttributeParams[0]?.goodsCustomerAttributeList?.length!=0){
setDefaultChecked(0)
}else{
setDefaultChecked(-1)
}
clickItemTab(-1)
setPriceAttributeParamsByRender(_priceAttributeParams)
setProductAttributeAndImageParams(_priceAttributeParams)
console.log(_priceAttributeParams, '_p')
// 初始化若是按所有属性共用做显示处理
if(setImageType){
setCommonImageList(_priceAttributeParams[0].commodityPic)
}
},[priceAttributeParams])
const clickItemTab = (_index: number) => {
// console.log(_index, '点击项')
console.log(_index, '点击项')
setDefaultChecked(_index)
// console.log(priceAttributeParams, 'params')
}
......@@ -110,16 +114,15 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
}
const beforeUpload = (file: UploadFile) => {
console.log(file,'file')
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg';
if (!isJpgOrPng) {
message.error('仅支持上传JPEG/JPG/PNG文件!')
}
const isLt2M = file.size / 1024 < 600;
if (!isLt2M) {
message.error('上传图片不超过2MB!');
const isLimit = file.size / 1024 < 600;
if (!isLimit) {
message.error('上传图片不超过600K!');
}
return isJpgOrPng && isLt2M && isSize(file, 800, 800);
return isJpgOrPng && isLimit && isSize(file, 800, 800);
}
//检测尺寸
const isSize = (file, w, h) => {
......@@ -153,31 +156,66 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
setPreviewTitle(file.name || file.url.substring(file.url.lastIndexOf('/') + 1))
}
const handleChange = ({ fileList }, index) => {
// console.log(priceAttributeParamsByRender, fileList, index, 'files change')
const handleChange = ({ file, fileList }, index) => {
let _priceAttributeParams = [...priceAttributeParamsByRender]
if(index===-1){ // -1表示所有属性共用 也表示表格只有默认的一行
console.log(_priceAttributeParams, '图片更改初始数据')
// if(index===-1){ // -1表示所有属性共用 也表示表格只有默认的一行 // 无需判断 不管是共用还是不共用都需要逐条写入fileList
setCommonImageList(fileList)
_priceAttributeParams[0].commodityPic = fileList
}else{
// _priceAttributeParams[0].commodityPic = fileList
// }else{
_priceAttributeParams[index].commodityPic = fileList
// }
if(!file?.status && file?.status !== 'done'){
// 不符合要求的 移除没有'done'状态的图片
if(index === -1){
let ttt = _priceAttributeParams[0].commodityPic.filter(_ => _.status === 'done')
setCommonImageList(ttt)
_priceAttributeParams[0].commodityPic = ttt
}else{
let ttt = _priceAttributeParams[index].commodityPic.filter(_ => _.status === 'done')
_priceAttributeParams[index].commodityPic = ttt
}
}
console.log(_priceAttributeParams, '图片更改之后数据')
setPriceAttributeParamsByRender(_priceAttributeParams)
setProductAttributeAndImageParams(_priceAttributeParams)
// console.log(_priceAttributeParams, '_priceAttributeParams')
}
return (<>
<div>
const onChangeSetImageType = (e) => {
setSetImageType(e.target.value)
setIsAllAttributePic(e.target.value)
if(e.target.value)
clickItemTab(-1)
else
clickItemTab(0)
// 切换 清空图片数组
let _priceAttributeParams = [...priceAttributeParamsByRender]
_priceAttributeParams.map(item => {
item.commodityPic = []
})
setPriceAttributeParamsByRender(_priceAttributeParams)
setProductAttributeAndImageParams(_priceAttributeParams)
setCommonImageList([])
}
return (<div>
<div style={{marginBottom:15}}>设置方式&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<Radio.Group onChange={onChangeSetImageType} value={setImageType}>
<Radio value={true}>所有属性共用商品图片(默认)</Radio>
<Radio value={false}>按属性设置商品图片</Radio>
</Radio.Group>
</div>
<div style={{ border: '1px solid rgba(223,225,230,1)' }}>
<Row>
<Col span={4} className={styles.colBox}>
<ul>
{priceAttributeParamsByRender?.length>0 && priceAttributeParamsByRender[0]?.goodsCustomerAttributeList?.length!=0 ? <span className={styles.tipTitle}>按特定属性添加图片</span>
: <li className={defaultChecked == -1 ? styles.activedLi : ""} onClick={()=>clickItemTab(-1)}>
<span>所有属性共用</span>
</li>
}
{
!setImageType ? <span className={styles.tipTitle}>按特定属性添加图片</span>
: <li className={defaultChecked == -1 ? styles.activedLi : ""} onClick={()=>clickItemTab(-1)}>
<span>所有属性共用</span>
</li>
}
{ !setImageType &&
priceAttributeParamsByRender?.length>0 && priceAttributeParamsByRender.map(
(item, index) => {
return Array.isArray(item.goodsCustomerAttributeList) &&
......@@ -195,6 +233,7 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
</Col>
<Col span={20} style={{ padding: 24 }}>
{
!setImageType &&
priceAttributeParamsByRender?.length>0 && priceAttributeParamsByRender[0]?.goodsCustomerAttributeList?.length!=0 ? priceAttributeParamsByRender.map((item, index) =>
<div key={index+100} style={defaultChecked == index ? {display: 'block'} : {display: 'none'}}>
<div className={styles.pictureCardBox}>
......@@ -223,7 +262,7 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
style={{ backgroundColor: '#F0F8FF', color: '#1B9AEE' }}
/>
</div>
)
)
: <div style={defaultChecked == -1 ? {display: 'block'} : {display: 'none'}}>
<div className={styles.pictureCardBox}>
<div className="clearfix">
......@@ -263,7 +302,7 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
<img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>
</div>
</>)
</div>)
}
export default observer(ProductImageForm)
\ No newline at end of file
......@@ -37,7 +37,7 @@ const SelectGoodsForm: React.FC<Iprops> = (props) => {
const { id } = history.location.query
if(id){
let _goodsArr: any = productInfoByEdit?.unitPriceAndPicList.map(_ => _.goods)
let goodsArr: any = _goodsArr.length>0 && Object.values(_goodsArr.reduce((item, next)=>{
let goodsArr: any = _goodsArr.toString() && _goodsArr.length>0 && Object.values(_goodsArr.reduce((item, next)=>{
item[next.id] = next;
return item
},{}))
......
......@@ -21,6 +21,9 @@ import { FORM_FILTER_PATH } from '@/formSchema/const'
import { createFormActions, FormEffectHooks } from '@formily/antd'
import { channelSchema } from './schema/channelSchema'
import { useAsyncInitSelect } from '@/formSchema/effects/useAsyncInitSelect'
import { PublicApi } from '@/services/api'
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect'
import { searchBrandOptionEffect, searchCustomerCategoryOptionEffect } from './effect'
// 定义选择的行数据的类型
interface Item {
......@@ -267,6 +270,12 @@ const DirectChannel: React.FC<{}> = () => {
}
}
// const fetchSelectBrand = async (params) => {
// const { data } = await PublicApi.getProductSelectGetSelectBrand({ name: params })
// console.log(params, data)
// return data
// }
const menuMore = (
<Menu onClick={(param) => handleMenuClick(param)}>
<Menu.Item key="2" icon={<VerticalAlignTopOutlined />}>
......@@ -320,13 +329,12 @@ const DirectChannel: React.FC<{}> = () => {
'name',
FORM_FILTER_PATH,
)
FormEffectHooks.onFieldInputChange$('brandId').subscribe(state => {
console.log(state, 'state')
FormEffectHooks.onFieldChange$('brandId').subscribe(state => {
searchBrandOptionEffect(actions, 'brandId')
})
FormEffectHooks.onFieldChange$('customerCategoryId').subscribe(state => {
searchCustomerCategoryOptionEffect(actions, 'customerCategoryId')
})
// useAsyncInitSelect(
// ['memberType', 'roleId', 'level', 'source'],
// fetchSearchItems,
// );
}}
schema={channelSchema}
/>
......
import React, { useEffect } from 'react'
import { ISchemaFormActions, FormEffectHooks, IFormActions } from '@formily/antd';
import { PublicApi } from '@/services/api';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
const { onFieldValueChange$ } = FormEffectHooks
// 高级筛选schema中用于输入搜索品牌的Effect
export const searchBrandOptionEffect = (context: any, fieldName: string) => {
context.getFieldState(fieldName, state => {
// console.log(state.props['x-component-props'].searchValue, 'pagesearchvalue') // 此处可以实时获取到输入并暂存在schema props的值
PublicApi.getProductSelectGetSelectBrand({ name: state.props['x-component-props'].searchValue }).then(res => {
context.setFieldState(fieldName, state => {
state.props['x-component-props'].dataOption = res.data
})
})
})
}
// 高级筛选schema中用于输入搜索商品品类的Effect
export const searchCustomerCategoryOptionEffect = (context: any, fieldName: string) => {
context.getFieldState(fieldName, state => {
PublicApi.getProductSelectGetSelectCustomerCategory({ name: state.props['x-component-props'].searchValue }).then(res => {
context.setFieldState(fieldName, state => {
state.props['x-component-props'].dataOption = res.data
})
})
})
}
\ No newline at end of file
import React, { useState, useEffect, useRef, ReactNode } from 'react'
import { history } from 'umi'
import { Button, Form, Card, Modal, Result, Progress, Select, Tooltip, Checkbox, Row, Col, Dropdown, Input, Menu, Popconfirm } from 'antd'
import { Button, Form, Card, Modal, Result, Progress, Select, Tooltip, Checkbox, Row, Col, Dropdown, Input, Menu, Popconfirm, message } from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import {
PlusOutlined,
......@@ -222,7 +222,7 @@ const Products: React.FC<{}> = () => {
</Menu.Item>
{(record.status === 4 || record.status === 6) ? <Menu.Item><Button type='link' onClick={() => clickUp(1, record.id)}>上架</Button></Menu.Item> : ''}
{record.status === 5 ? <Menu.Item><Button type='link' onClick={() => clickUp(0, record.id)}>下架</Button></Menu.Item> : ''}
{record.status === 3 ? <Menu.Item><Button type='link' onClick={() => clickModify(record.id)}>修改</Button></Menu.Item> : ''}
{record.status === 3 || record.status === 1 ? <Menu.Item><Button type='link' onClick={() => clickModify(record.id)}>修改</Button></Menu.Item> : ''}
<Menu.Item>
<Button type='link' onClick={()=>clickCopy(record)}>复制</Button>
</Menu.Item>
......@@ -412,7 +412,14 @@ const Products: React.FC<{}> = () => {
}
const onChangeUpShop = (values) => {
setCheckedValues(values)
// 判断上架之前是否有店铺 有即可以上下架
PublicApi.getTemplateShopFindShop().then(res => {
if(res.data.logo){
setCheckedValues(values)
}else{
message.error('您还没有开通店铺,无法上下架商品!')
}
})
}
const clickUp = (param: any, id: any) => { // param: 0 下架 1上架
......@@ -620,7 +627,7 @@ const Products: React.FC<{}> = () => {
defaultActiveFirstOption={false}
filterOption={false}
onSearch={handleBrandSearch}
onChange={handleBrandChange}
onChange={handleBrandChange}
notFoundContent={null}
style={{width:'100%'}}
>
......
......@@ -61,28 +61,89 @@ export const channelSchema: ISchema = {
filterOption: false,
notFoundContent: null,
style: { width: '174px', lineHeight: '32px' },
value: null,
searchValue: null,
dataOption: [],
},
},
customerCategoryId: {
type: 'string',
enum: [],
'x-component': 'CustomInputSearch',
'x-component-props': {
placeholder: '商品品类',
showSearch: true,
showArrow: true,
defaultActiveFirstOption: false,
filterOption: false,
notFoundContent: null,
style: { width: '174px', lineHeight: '32px' },
searchValue: null,
dataOption: []
},
},
status: {
type: 'string',
enum: [],
enum: [
{
label: '待提交审核',
value: 1,
},
{
label: '待审核',
value: 2,
}
],
'x-component-props': {
placeholder: '商品状态'
placeholder: '商品状态',
style: { width: '174px' },
},
},
price: {
type: 'string',
// price: {
// type: 'string',
// 'x-component-props': {
// placeholder: '商品价格'
// },
// },
'NO_NAME_FIELD_$2': {
type: 'object',
'x-component': 'layout',
'x-component-props': {
placeholder: '商品价格'
style: { width: '174px', display: 'flex', justifyContent: 'flex-start' },
},
properties: {
min: {
type: 'string',
"x-component-props": {
placeholder: '最低价',
type: 'number',
min: 0,
style: { width: '70px', textAlign: 'center', borderRight: 0 }
}
},
"gap": {
type: 'string',
"x-component-props": {
style: {
width: '34px',
borderLeft: 0,
borderRight: 0,
pointerEvents: 'none',
backgroundColor: '#fff',
textAlign: 'center'
},
placeholder: "~",
disabled: true,
}
},
max: {
type: 'string',
"x-component-props": {
placeholder: '最高价',
type: 'number',
min: 0,
style: { width: '70px', textAlign: 'center', borderLeft: 0 }
}
},
}
},
submit: {
'x-component': 'Submit',
......
......@@ -212,14 +212,23 @@ const viewProducts: React.FC<{}> = () => {
</Descriptions>
</>
/* 定价类型 */
//1-现货价格,2-价格需要询价,3-积分兑换商品
const renderPriceType = (type: number) => {
if(type === 1 ) return '现货价格'
if(type === 2 ) return '价格需要询价'
if(type === 3 ) return '积分兑换商品'
}
const renderDeliveryType = (type: number) => {
if(type === 1) return '物流(默认)'
if(type === 2) return '自提'
if(type === 3) return '无需配送'
}
const renderCarriageType = (type: number) => {
if(type === 1) return '卖家承担运费(默认)'
if(type === 2) return '买家承担运费'
}
/* 构建表格数据 */
const constructTableData = (productName: string, unitPriceAndPicList: GetProductCommodityGetCommodityResponse["unitPriceAndPicList"]) => {
// 构建列
......@@ -365,15 +374,15 @@ const viewProducts: React.FC<{}> = () => {
<p>配送方式:</p>
</Col>
<Col span={20}>
<p>物流(默认)</p>
<p>{renderDeliveryType(productDetail?.logistics?.deliveryType)}</p>
</Col>
</Row>
<Row>
<Col span={4}>
<p>方式:</p>
<p>方式:</p>
</Col>
<Col span={20}>
<p>买家承担运费</p>
<p>{renderCarriageType(productDetail?.logistics?.carriageType)}</p>
</Col>
</Row>
<Row>
......
......@@ -2,7 +2,7 @@
* @Author: LeeJiancong
* @Date: 2020-07-14 15:07:34
* @LastEditors: LeeJiancong
* @LastEditTime: 2020-08-19 10:53:33
* @LastEditTime: 2020-08-20 16:45:16
*/
import React, { Component, ReactNode, useRef, useState } from 'react'
import { history } from 'umi'
......@@ -122,7 +122,7 @@ const AddressList: React.FC<ListProps> = (props) => {
const [table, setTable] = useState([])
const [editingKey, setEditingKey] = useState('');
const toEdit = (id: number) => {
history.push(`/memberCenter/logisticsAbility/logistics/addressForm?type=${props.type}&id=${id}`)
history.push(`/memberCenter/logisticsAbility/logistics/addressForm?page_type=${props.type}&id=${id}`)
};
const columns: ColumnType<any>[] = [
{
......@@ -280,7 +280,7 @@ const AddressList: React.FC<ListProps> = (props) => {
formilyChilds={{
children: (
<>
<Button type="primary" icon={<PlusOutlined />} onClick={() => history.push(`/memberCenter/logisticsAbility/logistics/addressForm?type=${props.type}&id=0`)}>新建</Button>
<Button type="primary" icon={<PlusOutlined />} onClick={() => history.push(`/memberCenter/logisticsAbility/logistics/addressForm?page_type=${props.type}&id=0`)}>新建</Button>
</>
)
}}
......
import React, { useState, useRef, ReactNode } from 'react';
import { history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Input, Button } from 'antd';
import { ContainerOutlined } from '@ant-design/icons';
import { StandardTable } from 'god';
import React, { useContext, useState, useEffect, useRef } from 'react';
import {
Card,
Input,
Button,
Form,
message,
} from 'antd';
import { ColumnType } from 'antd/lib/table/interface';
import { PublicApi } from '@/services/api';
import { VIP_RULE_TRANSACTION, VIP_RULE_LOGIN, VIP_RULE_COMMENT } from '@/constants';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { ContainerOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
const EditableContext = React.createContext<any>({});
interface EditableRowProps {
index: number;
}
const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
interface EditableCellProps {
title: React.ReactNode;
editable: boolean;
children: React.ReactNode;
dataIndex: string;
index: number;
record: any;
rules: any;
handleSave: (record: any) => void;
addonAfter: React.ReactNode,
}
const EditableCell: React.FC<EditableCellProps> = ({
title,
editable,
children,
dataIndex,
index,
record,
rules = [],
addonAfter = null,
handleSave,
...restProps
}) => {
const [editing, setEditing] = useState(true);
const inputRef = useRef();
const form = useContext(EditableContext);
const inputId = `${dataIndex}-${index}`; // 拼接 name-index,不然全部展示输入框会警告 id 不唯一的问题
useEffect(() => {
if (editing) {
// inputRef.current.focus();
}
}, [editing]);
const toggleEdit = () => {
setEditing(!editing);
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
};
const save = async e => {
try {
const values = await form.validateFields();
// toggleEdit();
handleSave({
...record,
[dataIndex]: values[inputId],
});
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
let childNode = children;
if (editable) {
childNode = editing ? (
<Form.Item
style={{ margin: 0 }}
name={inputId}
rules={rules}
initialValue={record[dataIndex]}
>
<Input
ref={inputRef}
onPressEnter={save}
onBlur={save}
addonAfter={addonAfter}
/>
</Form.Item>
) : (
<div
className="editable-cell-value-wrap"
style={{ paddingRight: 24 }} onClick={toggleEdit}
>
{children}
</div>
);
}
const fetchData = async (params: any) => {
const res = await PublicApi.getMemberManageLevelRulePage(params);
return res.data;
return <td {...restProps}>{childNode}</td>;
};
interface Columns extends ColumnType<any> {
editable?: boolean;
rules?: Array<any>;
}
const MemberUpgradeRule: React.FC<[]> = () => {
const ref = useRef({});
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
const [total, setTotal] = useState(0);
const [dataSource, setDataSource] = useState([]);
const [listLoading, setListLoading] = useState(true);
const [submitLoading, setSubmitLoading] = useState(false);
const getRuleList = async (params) => {
setListLoading(true);
const res = await PublicApi.getMemberManageLevelRulePage(params);
if (res.code === 1000) {
const { data, totalCount } = res.data;
setDataSource(data);
setTotal(totalCount);
}
setListLoading(false);
};
const columns: ColumnType<any>[] = [
useEffect(() => {
getRuleList({
current: page,
pageSize: size,
});
}, [page, size]);
const columns: Columns[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
key: 'id',
},
{
title: '项目',
dataIndex: 'ruleName',
align: 'center',
key: 'ruleName',
render: (text: any, record: any) => <span>{text}</span>,
},
{
title: '项目说明',
dataIndex: 'remark',
align: 'center',
key: 'remark',
},
{
title: '可获取的分值',
dataIndex: 'point',
align: 'center',
key: 'point',
render: (text: any, record: any) => {
let component: ReactNode = null;
component =
record.id === 1 ? (
<Input
addonAfter="%"
value={record.point}
onChange={e => {
e.preventDefault();
record.point = e.target.value;
}}
/>
) : (
<Input value={record.point} />
);
return component;
},
width: '30%',
editable: true,
},
];
const handleSubmit = () => {};
const handlePaginationChange = (page: number, size: number) => {
setPage(page);
setSize(size);
};
// 重新保存 dataSource
const handleSave = row => {
const newData = [...dataSource];
const index = newData.findIndex(item => item.id === row.id);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
point: +row.point,
});
setDataSource(newData);
};
const handleSubmit = async () => {
if (!dataSource.length) {
return;
}
const payload = dataSource.map(item => ({
id: item.id,
point: item.point,
}));
setSubmitLoading(true);
const res = await PublicApi.postMemberManageLevelRuleSetpoint(payload);
if (res.code === 1000) {
message.success('保存成功');
getRuleList({
current: page,
pageSize: size,
});
}
setSubmitLoading(false);
};
const components = {
body: {
row: EditableRow,
cell: EditableCell,
},
};
const rulesMap = {
[VIP_RULE_TRANSACTION]: [
{
pattern: /^([0]|[1-9]+[0-9]*)(\.[0-9]+)?$/,
message: '请输入正确的格式',
},
],
[VIP_RULE_LOGIN]: [
{
pattern: /^[0]$|^[1-9]+[0-9]*$/,
message: '请输入正确的格式',
},
],
[VIP_RULE_COMMENT]: [
{
pattern: /^[0]$|^[1-9]+[0-9]*$/,
message: '请输入正确的格式',
},
],
};
const newColumns: any = columns.map(col => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record, index) => ({
handleSave,
record,
index,
dataIndex: col.dataIndex,
title: col.title,
editable: col.editable || false,
rules: [
{
required: true,
message: '请输入相应值',
},
...(rulesMap[record.ruleTypeEnum] || []),
],
addonAfter: record.ruleTypeEnum === VIP_RULE_TRANSACTION ? '%' : null,
}),
};
});
return (
<PageHeaderWrapper
......@@ -68,6 +272,7 @@ const MemberUpgradeRule: React.FC<[]> = () => {
<Button
type="primary"
icon={<ContainerOutlined />}
loading={submitLoading}
onClick={handleSubmit}
>
保存
......@@ -75,11 +280,23 @@ const MemberUpgradeRule: React.FC<[]> = () => {
}
>
<Card>
<div className="editable-row">
<div className="ant-form-explain">
123
</div>
</div>
<StandardTable
tableProps={{ rowKey: 'id' }}
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
dataSource={dataSource}
columns={newColumns}
components={components}
rowClassName={() => 'editable-row'}
loading={listLoading}
pagination={{
pageSize: size,
total,
}}
onPaginationChange={handlePaginationChange}
/>
</Card>
</PageHeaderWrapper>
......
.radio-group-box {
.ant-radio-button-wrapper {
width: 80px;
text-align: center;
}
}
\ No newline at end of file
import React, { Component, useState, useEffect } from 'react';
import { Modal, Button, Form,Radio } from 'antd'
import {
SchemaForm, SchemaMarkupField as Field,
createFormActions,
FormEffectHooks
} from '@formily/antd'
import { Input, FormMegaLayout } from '@formily/antd-components'
import { PublicApi } from '@/services/api'
export interface Params {
id?: any,
mode:number,
type?: number|string,
dialogVisible: boolean;
onCancel: Function;
onOK?: Function;
initialValues?: any;
dontReceive?: boolean; //默认展示
}
const actions = createFormActions()
const { onFieldChange$ } = FormEffectHooks
const comfirmDialog: React.FC<Params> = (props) => {
const handleCancel = () => {
}
const handletOk = (values: any) => {
let value = { ...values }
if(props.type){
value.type = props.type
}
console.log('列表',value)
props.onOK(value)
}
useEffect(() => {
return () => {
}
}, [])
const useFormEffects = () => {
const { setFieldState } = createFormActions()
}
return (
<>
<Modal
title={ props.mode === 0 ?'新增参数配置':'编辑参数配置'}
width={800}
visible={props.dialogVisible}
onOk={() => actions.submit()}
onCancel={() => props.onCancel()}
destroyOnClose
afterClose={() => actions.reset()}
okText={`确定`}
cancelText='取消'
>
<SchemaForm
labelCol={3}
components={{
Input, Radio: Radio.Group, TextArea: Input.TextArea
}}
actions={actions}
effects={() => useFormEffects()}
onSubmit={(values) => handletOk(values)}
initialValues={
props.initialValues
}
>
<Field
name='code'
title='参数代码'
required
x-component-props={{
placeholder: '',
}}
x-component="Input"
/>
<>
<Field
title='参数值'
name="value"
x-component="Input"
required
x-component-props={{
placeholder: '',
// addonBefore: ' '
}}
x-rules={{
message: ''
}}
/>
{/* <FormMegaLayout name='remarkOption' label='不接受原因' full required labelCol={2} labelAlign="top"> */}
<Field
title='参数描述'
name="describe"
x-component="TextArea"
x-component-props={{
placeholder: '最长128个字符'
}}
x-rules={{
max: 128,
// maximum:10,//最大数值
// message: '参数描述最多128个汉字'
}}
/>
</>
</SchemaForm>
</Modal>
</>
)
}
comfirmDialog.defaultProps = {
dontReceive: true,
type:1 //1.支付宝 2.支付宝转账到银行卡参数配置 3.微信
}
export default comfirmDialog
\ No newline at end of file
This diff is collapsed.
......@@ -13,6 +13,7 @@ class ProductStore implements IProductModule {
@observable public areaOption: any[] = [];
@observable public productInfoByEdit: GetProductCommodityGetCommodityResponse;
@observable public productDescription: IDecsParams;
@observable public isAllAttributePic: boolean = null; // 是否所有属性共用
/** 计算操作 **/
// 加工接口返回的数据,用户编辑回显数据
......@@ -37,11 +38,16 @@ class ProductStore implements IProductModule {
let attributeIdArr = attributeArr.map(item => item.id)
let attributeValueIdArr = attributeValueArr.map(item => item.map(_item => _item.id))
let tempObj = {}
console.log(attributeArr, attributeValueArr, this.attributeLists, this.productSelectAttribute,'store Item')
attributeIdArr.map((item, index) => {
if(attributeValueIdArr[index].length>1){
tempObj[item] = attributeValueIdArr[index]
}else{
tempObj[item] = attributeValueIdArr[index][0]
// 类型为2如果是一个的话 为配合checkbox Group也要生成数组
if(this.attributeLists.filter(_item => _item.id === item)[0]?.type === 2) // 多选
tempObj[item] = attributeValueIdArr[index]
else
tempObj[item] = attributeValueIdArr[index][0]
}
})
return tempObj
......@@ -125,6 +131,11 @@ class ProductStore implements IProductModule {
public setProductDescription(data: IDecsParams) {
this.productDescription = data
}
@action.bound
public setIsAllAttributePic(data: boolean) {
this.isAllAttributePic = data
}
}
......
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