触屏改版中后台业务组件封装与改造

包装产品ID链接组件

必要性

1.促销标签和分组标签模块列表详情表单可多处复用
2.含有不同环境跳转链接不同的逻辑

解决方案

在公共redux中加入请求当前环境接口,在组件中进行环境判断,给予相应跳转链接前缀

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

import React, { PropTypes } from "react";
import { connect } from "react-redux";
import { sysEnvSelector } from "../../common/redux/configSelector";

import { ENV } from "../../../common/config";
import { Link } from "react-router";
class ProdDetailLink extends React.PureComponent {
static propTypes = {
sysEnv: PropTypes.string.required,
param: PropTypes.object.required,
};
render() {
const { sysEnv, param } = this.props;
const domainName =
sysEnv === ENV.FAT ? "http://td.xyz.cn" : "http://d.xyz.cn";
return (
<Link
to={`${domainName}/product/pack/detail/${param && param.id}`}
target="_blank">
{param && param.id}
</Link>
);
}
}
const mapStateToProps = (state, props) => {
return {
sysEnv: sysEnvSelector(state),
};
};

export default connect(mapStateToProps)(ProdDetailLink);

表单自定义组件

必要性

1.开发过程中遇到复合表单组件,之间存在一定交互逻辑,预期能够将这些逻辑写在内部,而不是铺散在父组件中
2.方便后期维护

case 1

form.png

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import React, { PropTypes } from "react";
import {
promotionTagUploadProps,
promotionTagPicUploadProps,
imgPreviewUrl,
} from "../../../../common/config";

import { Radio } from "antd";
import SingleFileUpload from "../../../common/upload/singleFileUpload";
export const UserRangeType = {
ALL: "1",
SPECIAL: "2",
};
class UserRange extends React.PureComponent {
static propTypes = {
value: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
};

// attachmentList.push({
// uid: 1,
// name: info.viewImgId,
// url: `${fileDownloadUrl}/?fileIdEn=${info.viewImgId}`,
// attName: info.viewImgId,
// });

static defaultProps = {
value: {
type: UserRangeType.ALL,
},
};

onChange = (e) => {
const value = e.target.value;
this.props.onChange({
type: value,
extra: this.props.value.extra,
fileName: this.props.value.fileName,
});
};
onUploadChange = ({ fileIdEn, fileName }) => {
// this.setState()
this.props.onChange({
type: this.props.value.type,
extra: fileIdEn,
fileName: fileName,
});
};

render() {
return (
<div>
<Radio.Group onChange={this.onChange} value={this.props.value.type}>
<Radio value={UserRangeType.ALL}>全部用户</Radio>
<Radio value={UserRangeType.SPECIAL}>指定用户</Radio>
</Radio.Group>
<If condition={this.props.value.type === UserRangeType.SPECIAL}>
<div style={{ display: "flex" }}>
<a
href="https://file.xyz.cn/filesystem/download/26058002"
target="_blank">
下载模板
</a>
   
<SingleFileUpload
needFileName
value={
this.props.value.extra
? [
{
uid: -1212,
name: this.props.value.fileName,
url: `${imgPreviewUrl}/?fileIdEn=${this.props.value.extra}`,
attName: this.props.value.extra,
},
]
: ""
}
onChange={this.onUploadChange}
uploadProps={promotionTagUploadProps}
showTips="请上传xls、xlsx格式文件"
tipsStyle={{ color: "#c5cdcd", paddingLeft: 10 }}
/>
</div>
</If>
</div>
);
}
}

export default UserRange;

case 2

formCustom.png

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

import React, { PureComponent, PropTypes } from "react";
import { Select, AutoComplete, Input } from "antd";
import { getRecomendContentsByType } from "../../../../api/content";
const Option = Select.Option;
const contentTypes = [
{ name: "文章", code: "2", placeholder: "请输入文章id/标题搜索" },
{ name: "产品", code: "4", placeholder: "请输入包装产品id/主标题搜索" },
{ name: "专辑", code: "5", placeholder: "请输入专辑id/名称搜索" },
{ name: "指定url", code: "6" },
];
class RecomendSearch extends PureComponent {
static propTypes = {
onChange: PropTypes.func.isRequired,
params: PropTypes.object.isRequired,
callback:PropTypes.func.isRequired,
};
state = {
contents: [],
selectKey: "2",
};

//WARNING! To be deprecated in React v17. Use new lifecycle static getDerivedStateFromProps instead.
componentWillReceiveProps(nextProps) {}

componentDidMount() {
const { params } = this.props;
if (!params.id) {
this.onTypeChange("2");
}
}
onTypeChange = (_value) => {
const { onChange, value } = this.props;
let res = [
{
id: 1,
name: "wxxzdd sasaa",
},
{
id: 2,
name: "哈哈哈电放费",
},
{
id: 2,
name: "颠三倒四多所多",
},
];
// getRecomendContentsByType({ data: { recommendType: val } }, (res) => {
// res = res && res.map((item) => `${item.id} ${item.name}`);
// this.setState({
// contents: res,
// });
// });
res = res && res.map((item) => `${item.id}${item.name}`);
this.setState({
contents: res,
});
// this.setState({
// selectKey: value,
// });
onChange({
recommendType: _value,
value: _value === "6" ? "" : value && value.value,
});
};
onInputChange = (e) => {
console.log("e.target.value", e);
const { onChange } = this.props;
onChange({
recommendType: "6",
value: e.target.value,
});
};
onAutoCompeleteChange = (_value) => {
const { onChange, value } = this.props;
onChange({
value: _value,
recommendType: value && value.recommendType,
});
};
render() {
const { contents } = this.state;
const { value, params ,callback} = this.props;
return (
<div style={{ display: "flex" }}>
<Select
style={{ width: "60%", marginRight: 18 }}
onChange={this.onTypeChange}
value={(value && value.recommendType) || "2"}>
{contentTypes.map((item) => (
<Option value={item.code} key={item.code}>
{item.name}
</Option>
))}
</Select>
<Choose>
<When condition={(value && value.recommendType) === "6"}>
<Input
placeholder={"请输入指定url"}
onChange={this.onInputChange}
value={value && value.value}
/>
</When>
<Otherwise>
<AutoComplete
placeholder={
contentTypes.find(
(item) => item.code === (value && value.recommendType)
).placeholder
}
dataSource={contents}
filterOption={(inputValue, option) =>
option.props.children
.toUpperCase()
.includes(inputValue.toUpperCase())
}
onChange={this.onAutoCompeleteChange}
onSelect={callback}
value={value && value.value}
/>
</Otherwise>
</Choose>
</div>
);
}
}

export default RecomendSearch;

上传组件改造

必要性

1.上传组件很多场景只需上传一个
2.以前的FileUpload组件 onChange返回的是一个fileList ,而很多场景只需要一个fileIdEn给后端
3.table里上传后下载链接点击失效的bug修复,不影响其他的FileUpload组件使用
4.对当前业务的其他定制需求

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

/*
* @Author: zhangyunpeng
* @Date: 2020-06-24 16:15:32
* @Last Modified by: zhangyunpeng
* @Last Modified time: 2020-07-01 11:35:19
* @Summary: 因为 FileUpload onChange 传出的值考虑上传 多个
* 并非fileIdEn 实现单个传出fileIdEn 表单简化
*/

import React ,{PropTypes}from "react";
import FileUpload from "./fileUpload";

class SingleFileUpload extends React.PureComponent {

static propTypes={
// 是否向父组件暴露文件名
needFileName:PropTypes.bool,
onChange:PropTypes.func.isRequired,

}
componentDidUpdate() {
// 修复在table中点击上传之后文件链接无法下载bug
const childDom = document.querySelector(
".ant-upload-list-item-info span a"
);
childDom &&
childDom.addEventListener(
"click",
function (e) {
e.preventDefault();
window.open(childDom.getAttribute("href"));
},
false
);
}

componentWillUnmount() {
const childDom = document.querySelector(
".ant-upload-list-item-info span a"
);
childDom &&
childDom.removeEventListener(
"click",
function (e) {
e.preventDefault();
window.open(childDom.getAttribute("href"));
},
false
);
}

componentDidMount() {}
render() {
const { onChange, needFileName = false, ...restProps } = this.props;
const _onChange = (fileList) => {
// console.log('fileList[0]',fileList[0])
const fileName = fileList[0].name;
const fileIdEn =
fileList[0].response && fileList[0].response.data.fileIdEn;
if (needFileName) {
onChange({ fileIdEn, fileName });
} else {
onChange(fileIdEn);
}
};

return <FileUpload {...restProps} onChange={_onChange} />;
}
}

export default SingleFileUpload;

列表工具2.0组件二次封装

必要性

1.根据业务需要,定义一些table常用属性
2.修复一些样式问题

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
* @Author: zhangyunpeng
* @Date: 2020-06-23 11:03:18
* @Last Modified by: zhangyunpeng
* @Last Modified time: 2020-07-02 15:02:24
* @Summary: 产品促销列表
*/

import React from "react";
import ListToolPageHOC from "@xyz/listtool/src/components/ListToolPageHOC";
import _ from "lodash";



const outContext = {
request: {

},
};


const ListToolPage = ListToolPageHOC(outContext);
class List extends React.PureComponent {



render() {
const { props, ...restProps } = this.props;

const _props = {
...props,
listCardProps: { className: "ant-card-no-hovering" },
pageProps: {
pageSizeOptions: ["10", "20", "30", "40"],
},
};


return <ListToolPage {...restProps} props={_props} />;
}
}


export default List;
查看评论