Commit 5fcc38dc authored by 邓晓峰's avatar 邓晓峰

Merge branch 'feature/ImageSelect' into 'dev'

feat: 图片选择组件 See merge request !2
parents 83000281 2499ae35
Pipeline #24142 failed with stages
in 1 minute 30 seconds
......@@ -99,7 +99,7 @@ export default {
},
{
title: '通用',
children: ['Empty'],
children: ['ImageSelect'],
},
{
title: '数据录入',
......
# `@wisdom-components/ImageSelect`
> TODO: description
## Usage
```
const imageselect = require('@wisdom-components/ImageSelect');
// TODO: DEMONSTRATE API
```
{
"name": "@wisdom-components/imageselect",
"version": "1.0.1",
"description": "> TODO: description",
"author": "tuqian <webtuqian@163.com>",
"homepage": "",
"license": "ISC",
"main": "lib/index.js",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"publishConfig": {
"registry": "https://g.civnet.cn:4873/"
},
"repository": {
"type": "git",
"url": "https://g.civnet.cn:8443/ReactWeb5/wisdom-components.git"
},
"scripts": {
"test": "echo \"Error: run tests from root\" && exit 1"
}
}
---
title: ImageSelect - 图片选择
nav:
title: 组件
path: /components
group:
path: /
---
# ImageSelect 图片选择
基础业务组件
- 允许单文件夹下图片选择
- 允许多文件夹下图片选择
- 允许搜索、自动定位选中图片
## 何时使用
- 在系统图片选择时。
- 在设备图例选择时。
## 代码演示
<code src="./demos/Basic.js">
## API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| src | 封面图片地址 | string | - |
| url | 默认 url 地址 | string | window.location.origin |
| dataSource | 模态框数据源 | array | - |
| width | 模态框宽度 | number | 700 |
| title | 模态框标题 | string | 点击选择图片文件 |
| onSearch | 搜索框输入事件的回调,会返回搜索框输入信息 | function(value){ } | - |
| onSelect | 选中模态框的图片后的回调,会返回选中图片信息 | function(value){ } | - |
import React from 'react';
import PandaImageSelect from '../index';
import request from 'umi-request';
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
Authorization: '',
};
}
onSelect = (value) => {
console.log(value, 'PandaImageSelect-value');
};
fetchData = (params = {}) => {
const _this = this;
const { Authorization } = this.state;
request(baseUrl + '/Publish/OMS/FileCenter/GetImageOrderByPath', {
headers: { Authorization },
method: 'get',
params: {
path: 'assets/images/appMenu',
maxLength: 279.1525423728813,
fileName: params.fileName ? params.fileName : '',
},
}).then(function (response) {
_this.setState({
dataSource: response.data,
});
});
};
// 获取token
componentDidMount() {
const _this = this;
request(baseUrl + '/Publish/GateWay/OMS/OMSLogin', {
method: 'post',
requestType: 'form',
data: {
userName: 'omsa',
password: 'pandaomsa',
},
})
.then(function (response) {
if (response.data.token) {
const { access_token, token_type } = response.data.token;
_this.setState(
{
Authorization: token_type + ' ' + access_token,
},
() => {
_this.fetchData();
},
);
}
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<PandaImageSelect
onSearch={(params) => this.fetchData(params)}
dataSource={this.state.dataSource}
onSelect={(value) => this.onSelect(value)}
url={baseUrl}
/>
);
}
}
export default Demo;
const baseUrl = 'http://192.168.10.150:8777'; // window.location.origin
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
// import request from "umi-request";
import { Input, Image, Modal, Row, Col } from 'antd';
import Empty from '@wisdom-components/Empty';
import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
import styles from './index.less';
const ImageSelect = ({ src, url, width, title, dataSource, onSearch, onSelect }) => {
const baseUrl = url ? url : window.location.origin;
const imgList = dataSource.map((item) => {
return {
list: item.list,
text: item.text,
};
});
const [visible, setVisible] = useState(false);
const [imgSrc, setImgSrc] = useState(src);
// 展示模态框
const showModal = () => {
setVisible(true);
};
// 关闭模态框
const handleCancel = () => {
setVisible(false);
};
// 搜索框内容变化时的回调
const onChange = (e) => {
if (e.target.value === '') onPressEnter(e);
};
// 搜索框按下回车的回调
const onPressEnter = (e) => {
onSearch({ fileName: e.target.value });
};
// 选中模态框中的图片
const handleSelect = (e, item) => {
setImgSrc(item.value);
onSelect && onSelect({ ...item, url: baseUrl + item.value });
handleCancel();
};
const renderImageList = (data = []) => {
return (
<Row gutter={[0, 24]}>
{!!data &&
data.map((item, index) => (
<Col
span={4}
key={item.value + index}
className={[styles.itemBox, imgSrc === item.value ? styles.selected : null]}
onClick={(e) => handleSelect(e, item)}
>
<Image
className={styles.itemImg}
preview={false}
src={baseUrl + item.value}
title={item.text}
/>
<div className={styles.itemText}>
{item.text ? item.text.split('.')[0] : item.text}
</div>
</Col>
))}
</Row>
);
};
return (
<div className={styles.ImageSelect}>
<div className={styles.pandaImg} onClick={showModal}>
{!!imgSrc && <Image className={styles.coverImg} preview={false} src={baseUrl + imgSrc} />}
{!imgSrc && (
<div>
<PlusOutlined />
<p>点击选择图片</p>
</div>
)}
</div>
<Modal
width={width}
centered
title={
<div className={styles.header}>
<div className={styles.title}>{title}</div>
<Input
className={styles.search}
placeholder="搜索图片关键词"
allowClear
bordered={false}
prefix={<SearchOutlined />}
onChange={onChange}
onPressEnter={onPressEnter}
/>
</div>
}
footer={null}
visible={visible}
onCancel={handleCancel}
className={styles.ImageSelectModal}
>
{!!imgList.length &&
imgList.map((item, index) => {
return (
<div key={item.text + index} className={styles.folder}>
<div className={styles.pathTitle}>{item.text}</div>
<div>{renderImageList(item.list)}</div>
</div>
);
})}
{!imgList.length && <Empty />}
</Modal>
</div>
);
};
ImageSelect.defaultProps = {
src: '', // 封面图片地址
url: '', // 默认url地址
dataSource: [], // 模态框数据源
width: 700, // 模态框宽度
title: '点击选择图片文件', // 模态框宽度
onSearch: function (v) {}, // 搜索框输入事件的回调
onSelect: function (v) {}, // 模态框选中的图片的回调
};
ImageSelect.propTypes = {
src: PropTypes.string, // 封面图片地址
url: PropTypes.string, // 默认url地址
dataSource: PropTypes.array, // 模态框数据源
width: PropTypes.number, // 模态框宽度
title: PropTypes.string, // 模态框标题
onSearch: PropTypes.func, // 搜索框输入事件的回调
onSelect: PropTypes.func, // 模态框选中的图片的回调
};
export default ImageSelect;
.ImageSelect {
.pandaImg {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
padding: 5px;
text-align: center;
background-color: rgba(250, 251, 252, 1);
border: 1px solid rgba(219, 225, 234, 1);
overflow: hidden;
cursor: pointer;
.coverImg {
width: 88px;
height: 88px;
}
p {
font-size: 12px;
}
}
}
.ImageSelectModal {
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-right: 30px;
.title {
font-size: 16px;
font-weight: 500;
color: #222222;
}
.search {
width: 313px;
height: 29px;
background: #eef1f9;
border-radius: 15px;
:global {
.ant-input-prefix {
color: #5a6c8a;
}
}
input {
background: #eef1f9;
}
}
}
.folder {
border-top: 1px solid #ccd6e1;
.pathTitle {
font-size: 16px;
color: #242323;
margin: 20px 0;
}
.itemBox {
text-align: center;
border: 1px solid transparent;
.itemImg {
width: 40px;
height: 40px;
}
&:hover {
cursor: pointer;
border: 1px solid #b8d6fb;
background: linear-gradient(0deg, #f1f4fb 0%, #ffffff 100%);
border-radius: 2px;
}
}
.selected {
border: 1px solid #b8d6fb;
background: linear-gradient(0deg, #f1f4fb 0%, #ffffff 100%);
border-radius: 2px;
}
.itemText {
font-size: '12px';
white-space: 'nowrap';
}
&:first-of-type {
border: none;
.pathTitle {
margin-top: 0;
}
}
}
:global {
.ant-modal-body {
max-height: 600px;
overflow-y: auto;
}
}
}
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