first commit
This commit is contained in:
16
src/components/BottomBar/NavLink.js
Normal file
16
src/components/BottomBar/NavLink.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import ReactSVG from 'react-svg'
|
||||
import {NavLink} from 'react-router-dom';
|
||||
|
||||
/*
|
||||
to
|
||||
src
|
||||
text
|
||||
*/
|
||||
|
||||
export default (props) => (
|
||||
<NavLink className="nav" to={props.to} activeClassName="nav-active" exact>
|
||||
<ReactSVG src={props.src} className="svg"></ReactSVG>
|
||||
<span className="nav-text">{props.text}</span>
|
||||
</NavLink>
|
||||
);
|
||||
41
src/components/BottomBar/bottom-bar.scss
Normal file
41
src/components/BottomBar/bottom-bar.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
// 底部菜单
|
||||
.bottom-bar {
|
||||
display: flex;
|
||||
// justify-content: space-between;
|
||||
font-size: .2rem;
|
||||
height: 1rem;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: white;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid $gray;
|
||||
.nav {
|
||||
flex: 1;
|
||||
color: $sliver;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 .2rem;
|
||||
.svg {
|
||||
svg {
|
||||
fill: $sliver;
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nav-active {
|
||||
color: $blue;
|
||||
.svg {
|
||||
svg {
|
||||
fill: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/components/BottomBar/index.js
Normal file
21
src/components/BottomBar/index.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import React, { Component } from 'react';
|
||||
import './bottom-bar.scss';
|
||||
import NavLink from './NavLink';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
import {IndexList} from '@/router';
|
||||
|
||||
class BottomBar extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="bottom-bar">
|
||||
{
|
||||
IndexList.map((link, index) => (
|
||||
<NavLink key={index} {...link} to={link.to}></NavLink>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(BottomBar);
|
||||
68
src/components/Button/button.scss
Normal file
68
src/components/Button/button.scss
Normal file
@@ -0,0 +1,68 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
$fontSize: .28rem;
|
||||
.btn {
|
||||
font-size: $fontSize;
|
||||
outline: none;
|
||||
padding: .2rem;
|
||||
border: 1px solid $gray;
|
||||
border-radius: .1rem;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
// box-shadow: 0 0 .05rem rgba($lightGray, .8);
|
||||
// text-shadow: 1px 1px 1px rgba($black, 1);
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
background: white;
|
||||
color: $black;
|
||||
}
|
||||
.btn-primary {
|
||||
background: $primary;
|
||||
}
|
||||
.btn-success {
|
||||
background: $success;
|
||||
}
|
||||
.btn-warning {
|
||||
background: $warning;
|
||||
}
|
||||
.btn-danger {
|
||||
background: $danger;
|
||||
}
|
||||
.btn-disable {
|
||||
// opacity: .6;
|
||||
color: $gray;
|
||||
background: white;
|
||||
cursor:not-allowed;
|
||||
}
|
||||
|
||||
.btn-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: .9rem;
|
||||
width: 100%;
|
||||
}
|
||||
.btn-loading {
|
||||
display: inline-block;
|
||||
width: $fontSize;
|
||||
height: $fontSize;
|
||||
margin-right: .1rem;
|
||||
box-sizing: border-box;
|
||||
border: .04rem solid $lightGray;
|
||||
border-radius: 50%;
|
||||
border-right-color: transparent;
|
||||
animation: btnRotate .5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes btnRotate {
|
||||
from {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
55
src/components/Button/index.js
Normal file
55
src/components/Button/index.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import React, {Component} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './button.scss';
|
||||
|
||||
/*
|
||||
props:
|
||||
type: null btn-default
|
||||
primary
|
||||
success
|
||||
warning
|
||||
danger
|
||||
disabled boo
|
||||
block boo
|
||||
loading boo 是否是loading状态
|
||||
extraClass str 额外的样式
|
||||
|
||||
nativeType 原生type
|
||||
*/
|
||||
|
||||
class Button extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
}
|
||||
onClick (e) {
|
||||
if (!this.props.loading) {
|
||||
this.props.onClick && this.props.onClick(e);
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<button
|
||||
className={
|
||||
classNames(
|
||||
'btn',
|
||||
this.props.type ? `btn-${this.props.type}`: 'btn-default',
|
||||
{'btn-block': this.props.block},
|
||||
{'btn-disable': this.props.disabled},
|
||||
this.props.extraClass
|
||||
)}
|
||||
type={this.props.nativeType}
|
||||
disabled={this.props.disabled}
|
||||
onClick={this.onClick.bind(this)}
|
||||
>
|
||||
{
|
||||
this.props.loading && (
|
||||
<span className="btn-loading"></span>
|
||||
)
|
||||
}
|
||||
{this.props.children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Button;
|
||||
139
src/components/Dialog/Dialog.jsx
Normal file
139
src/components/Dialog/Dialog.jsx
Normal file
@@ -0,0 +1,139 @@
|
||||
import React, {Component} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './dialog.scss';
|
||||
import BScroll from 'better-scroll';
|
||||
|
||||
import Animated from 'animated/lib/targets/react-dom'
|
||||
|
||||
/*
|
||||
Dialog2.show('错误', desc, {
|
||||
// showCancel: ,
|
||||
// cancelText: '',
|
||||
confirmText: '是的'
|
||||
}, res => {
|
||||
console.log(res);
|
||||
});
|
||||
*/
|
||||
|
||||
class Dialog extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
options: {
|
||||
showCancel: true,
|
||||
cancelText: '',
|
||||
confirmText: ''
|
||||
},
|
||||
ani: new Animated.Value(0)
|
||||
};
|
||||
this.func = null;
|
||||
this.scroll = null;
|
||||
}
|
||||
async componentDidMount () {
|
||||
this.setState({
|
||||
title: this.props.title,
|
||||
message: this.props.message,
|
||||
})
|
||||
if (this.props.options) this.setState({
|
||||
'options': {
|
||||
...this.state.options,
|
||||
...this.props.options
|
||||
}
|
||||
})
|
||||
if (this.props.func) this.func = this.props.func;
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 1,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
// console.log('入长了')
|
||||
const code105Div = document.querySelector('.code105')
|
||||
console.log(code105Div)
|
||||
if (code105Div) {
|
||||
this.scroll = new BScroll(code105Div, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
clickMask () {
|
||||
this.fnClick(null);
|
||||
}
|
||||
fnClose () {
|
||||
this.fnClick(false);
|
||||
}
|
||||
fnConfirm () {
|
||||
this.fnClick(true);
|
||||
}
|
||||
fnClick (boo) {
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(async () => {
|
||||
// await this.setState({show: false});
|
||||
// 移除dom
|
||||
try {
|
||||
ReactDOM.unmountComponentAtNode(oDiv);
|
||||
document.body.removeChild(oDiv);
|
||||
this.func && this.func(boo);
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="dialog">
|
||||
<Animated.div className="mask" onClick={this.clickMask.bind(this)} style={{opacity: this.state.ani}}>
|
||||
<div className="dia-wrapper" onClick={e => e.stopPropagation()}>
|
||||
<div className="dia-head">
|
||||
{/* 标题 */}
|
||||
{
|
||||
this.state.title && (
|
||||
<div className="title">{this.state.title || '标题'}</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className="dia-body">
|
||||
{/* 内容 */}
|
||||
<div className="message" dangerouslySetInnerHTML={{__html: this.state.message || '内容'}}></div>
|
||||
</div>
|
||||
<div className="dia-footer">
|
||||
{/* 底部按钮 */}
|
||||
{
|
||||
this.state.options.showCancel && (
|
||||
<div className="btn btn-cancel" onClick={this.fnClose.bind(this)}>{this.state.options.cancelText || '取消'}</div>
|
||||
)
|
||||
}
|
||||
<div className="btn btn-confirm" onClick={this.fnConfirm.bind(this)}>{this.state.options.confirmText || '确定'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let oDiv = null;
|
||||
|
||||
Dialog.show = (title, message, options, fn) => {
|
||||
let props = {
|
||||
show: true,
|
||||
title,
|
||||
message,
|
||||
options,
|
||||
func: fn
|
||||
}
|
||||
|
||||
oDiv = document.createElement('div');
|
||||
document.body.appendChild(oDiv);
|
||||
ReactDOM.render(React.createElement(Dialog, props), oDiv);
|
||||
}
|
||||
|
||||
export default Dialog;
|
||||
76
src/components/Dialog/dialog.scss
Normal file
76
src/components/Dialog/dialog.scss
Normal file
@@ -0,0 +1,76 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
// dialog 对话框
|
||||
.dialog {
|
||||
font-size: .32rem;
|
||||
.mask {
|
||||
position: fixed;
|
||||
z-index: 9000;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
background: rgba(black, .6);
|
||||
}
|
||||
.dia-wrapper {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
border-radius: .1rem;
|
||||
width: 4.5rem;
|
||||
}
|
||||
.dia-head {
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
padding: .2rem;
|
||||
color: $extraLightBlack;
|
||||
}
|
||||
.dia-body {
|
||||
padding: .2rem;
|
||||
text-align: center;
|
||||
font-size: .3rem;
|
||||
color: $black;
|
||||
word-break: break-all;
|
||||
.message {
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
.dia-footer {
|
||||
display: flex;
|
||||
margin-top: .2rem;
|
||||
border-top: 1px solid $gray;
|
||||
align-items: center;
|
||||
}
|
||||
$btn-height: .8rem;
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: $btn-height;
|
||||
line-height: $btn-height;
|
||||
text-align: center;
|
||||
}
|
||||
.btn:nth-of-type(2) {
|
||||
border-left: 1px solid $gray;
|
||||
}
|
||||
.btn-cancel {
|
||||
color: $sliver;
|
||||
}
|
||||
.btn-confirm {
|
||||
color: $blue;
|
||||
font-weight: 500;
|
||||
}
|
||||
.success {
|
||||
color: $success;
|
||||
}
|
||||
.address {
|
||||
font-size: .26rem;
|
||||
color: $sliver;
|
||||
}
|
||||
.error {
|
||||
color: $danger;
|
||||
}
|
||||
.warning {
|
||||
color: $warning;
|
||||
}
|
||||
}
|
||||
26
src/components/Dialog/index.js
Normal file
26
src/components/Dialog/index.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import Dialog from './Dialog.jsx';
|
||||
|
||||
/*
|
||||
Dialog2.show('错误', desc, {
|
||||
showCancel: true,
|
||||
cancelText: '',
|
||||
confirmText: '是的'
|
||||
}, res => {
|
||||
console.log(res); // true false
|
||||
});
|
||||
*/
|
||||
|
||||
export default {
|
||||
show (title, message, options, fn) {
|
||||
Dialog.show(title, message, options, fn);
|
||||
},
|
||||
showErr (e) {
|
||||
let msg = e
|
||||
if (Object.prototype.toString(e).indexOf('Error') > -1) {
|
||||
msg = e.message
|
||||
}
|
||||
Dialog.show('错误', msg, {
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
};
|
||||
59
src/components/Dialog2/dialog.scss
Normal file
59
src/components/Dialog2/dialog.scss
Normal file
@@ -0,0 +1,59 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
// dialog 对话框
|
||||
.dialog {
|
||||
font-size: .32rem;
|
||||
.mask {
|
||||
position: fixed;
|
||||
z-index: 9000;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
background: rgba(black, .6);
|
||||
}
|
||||
.dia-wrapper {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
border-radius: .1rem;
|
||||
width: 4.5rem;
|
||||
}
|
||||
.dia-head {
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
padding: .2rem;
|
||||
color: $extraLightBlack;
|
||||
}
|
||||
.dia-body {
|
||||
padding: .2rem;
|
||||
text-align: center;
|
||||
font-size: .3rem;
|
||||
color: $black;
|
||||
}
|
||||
.dia-footer {
|
||||
display: flex;
|
||||
margin-top: .2rem;
|
||||
border-top: 1px solid $gray;
|
||||
align-items: center;
|
||||
}
|
||||
$btn-height: .8rem;
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: $btn-height;
|
||||
line-height: $btn-height;
|
||||
text-align: center;
|
||||
}
|
||||
.btn:nth-of-type(2) {
|
||||
border-left: 1px solid $gray;
|
||||
}
|
||||
.btn-cancel {
|
||||
color: $sliver;
|
||||
}
|
||||
.btn-confirm {
|
||||
color: $blue;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
107
src/components/Dialog2/index.js
Normal file
107
src/components/Dialog2/index.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import React, {Component} from 'react';
|
||||
import './dialog.scss';
|
||||
|
||||
import Animated from 'animated/lib/targets/react-dom'
|
||||
|
||||
/*
|
||||
this.refs.dialog.show('', '成功注册!', {
|
||||
// showCancel: false,
|
||||
confirmText: '知道了'
|
||||
}, confirm => {
|
||||
console.log(confirm);
|
||||
});
|
||||
*/
|
||||
|
||||
class Dialog extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
options: {
|
||||
showCancel: true,
|
||||
cancelText: '',
|
||||
confirmText: ''
|
||||
},
|
||||
ani: new Animated.Value(0)
|
||||
}
|
||||
}
|
||||
async show (title, message, options, func) {
|
||||
this.setState({
|
||||
show: true,
|
||||
title,
|
||||
message
|
||||
});
|
||||
if (options) this.setState({
|
||||
'options': {
|
||||
...this.state.options,
|
||||
...options
|
||||
}
|
||||
});
|
||||
if (func) this.func = func;
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 1,
|
||||
duration: 400
|
||||
}).start();
|
||||
}
|
||||
clickMask () {
|
||||
this.fnClose();
|
||||
}
|
||||
fnClose () {
|
||||
this.func && this.func(false);
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false});
|
||||
});
|
||||
}
|
||||
fnConfirm () {
|
||||
this.func && this.func(true);
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false});
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="dialog">
|
||||
{
|
||||
this.state.show && (
|
||||
<Animated.div className="mask" onClick={this.clickMask.bind(this)} style={{opacity: this.state.ani}}>
|
||||
<div className="dia-wrapper" onClick={e => e.stopPropagation()}>
|
||||
<div className="dia-head">
|
||||
{/* 标题 */}
|
||||
{
|
||||
this.state.title && (
|
||||
<div className="title">{this.state.title || '标题'}</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className="dia-body">
|
||||
{/* 内容 */}
|
||||
<div className="message">{this.state.message || '内容'}</div>
|
||||
</div>
|
||||
<div className="dia-footer">
|
||||
{/* 底部按钮 */}
|
||||
{
|
||||
this.state.options.showCancel && (
|
||||
<div className="btn btn-cancel" onClick={this.fnClose.bind(this)}>{this.state.options.cancelText || '取消'}</div>
|
||||
)
|
||||
}
|
||||
<div className="btn btn-confirm" onClick={this.fnConfirm.bind(this)}>{this.state.options.confirmText || '确定'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Dialog;
|
||||
127
src/components/Form.js
Normal file
127
src/components/Form.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import React, { Component } from 'react';
|
||||
import './form.scss';
|
||||
import Toast from '@/components/Toast';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
|
||||
/*
|
||||
getFormData
|
||||
*/
|
||||
|
||||
class Form extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
list: {},
|
||||
focus: '',
|
||||
num: 0
|
||||
}
|
||||
}
|
||||
async componentDidMount () {
|
||||
for (let i = 0; i < this.props.fields.length; i++) {
|
||||
await this.setState({
|
||||
list: {
|
||||
...this.state.list,
|
||||
[this.props.fields[i].name]: this.props.fields[i].value
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// input focus
|
||||
fnFocus (name) {
|
||||
console.log(name);
|
||||
this.setState({focus: name});
|
||||
}
|
||||
fnBlur () {
|
||||
console.log('失去焦点');
|
||||
// this.setState({focus: ''});
|
||||
}
|
||||
// input 修改
|
||||
async fnChange (name, e) {
|
||||
// console.log(name, e.target.value);
|
||||
// this[name] = e.target.value;
|
||||
await this.setState({
|
||||
list: {
|
||||
...this.state.list,
|
||||
[name]: e.target.value
|
||||
}
|
||||
})
|
||||
// console.log(this.state);
|
||||
}
|
||||
// 清除
|
||||
fnClear (name) {
|
||||
// console.log('清除' + name);
|
||||
this.refs[name].value = '';
|
||||
this.setState({
|
||||
list: {
|
||||
...this.state.list,
|
||||
[name]: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获得formData
|
||||
getFormData () {
|
||||
let form = new FormData(this.refs.form);
|
||||
return form;
|
||||
}
|
||||
// 发送验证码
|
||||
async fnSendCode (name) {
|
||||
if (!/^\d{11}$/.test(this.state.list[name]) || this.state.num > 0) return false;
|
||||
let tel = this.state.list[name];
|
||||
console.log(tel);
|
||||
let form = new FormData();
|
||||
form.append('authID', tel);
|
||||
form.append('authToken', this.props.token);
|
||||
try {
|
||||
await fetchJson('/v2/auth2/SendVerifyCode', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
this.refs.toast.show('短信发送成功');
|
||||
// 开始倒计时
|
||||
await this.setState({num: 59});
|
||||
clearInterval(this.timer);
|
||||
this.timer = setInterval(() => {
|
||||
if (this.state.num === 0) {
|
||||
clearInterval(this.timer);
|
||||
} else {
|
||||
this.setState({num: --this.state.num});
|
||||
}
|
||||
}, 1000);
|
||||
} catch (e) {
|
||||
this.refs.toast.show(e);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
if (!this.props.fields) console.error('Form need fields');
|
||||
return (
|
||||
<form ref="form" className="form">
|
||||
{
|
||||
this.props.fields.length > 0 && (
|
||||
this.props.fields.map((field, index) => (
|
||||
<div className="form-item" key={index}>
|
||||
<label className={'icon ' + field.icon} htmlFor={field.name}></label>
|
||||
<input ref={field.name} type={field.name} placeholder={field.placeholder} name={field.name} id={field.name} defaultValue={field.value} onChange={this.fnChange.bind(this, field.name)} onFocus={this.fnFocus.bind(this, field.name)} onBlur={this.fnBlur.bind(this)}/>
|
||||
{/* // 清空按钮 */}
|
||||
{
|
||||
(this.state.focus === field.name && this.state.list[field.name]) && (
|
||||
<div className="clear" onClick={this.fnClear.bind(this, field.name)}></div>
|
||||
)
|
||||
}
|
||||
{/* // 其他按钮 */}
|
||||
{
|
||||
field.btn && (
|
||||
<div className={this.state.list[field.name] && this.state.list[field.name].length === 11 && this.state.num === 0 ? 'btn-getcode' : 'btn-getcode disabled'} onClick={this.fnSendCode.bind(this, field.name)}>{field.btn.name}{this.state.num > 0 && '(' + this.state.num + ')'}</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
))
|
||||
)
|
||||
}
|
||||
<Toast ref="toast"></Toast>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Form;
|
||||
93
src/components/Loading/Loading.jsx
Normal file
93
src/components/Loading/Loading.jsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import React, {Component} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './loading.scss';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
|
||||
/*
|
||||
用法:
|
||||
// 显示
|
||||
Loading.show();
|
||||
// 隐藏
|
||||
Loading.hide();
|
||||
*/
|
||||
|
||||
class Loading extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
ani: new Animated.Value(1),
|
||||
loading: false
|
||||
}
|
||||
}
|
||||
componentDidMount () {
|
||||
// this.disableScroll();
|
||||
this.setState({loading: true})
|
||||
}
|
||||
// 锁定滚动
|
||||
disableScroll () {
|
||||
const documentBody = document.body;
|
||||
if (documentBody) {
|
||||
documentBody.style.setProperty('overflow', 'hidden');
|
||||
}
|
||||
}
|
||||
// 允许滚动
|
||||
enableScroll () {
|
||||
const documentBody = document.body;
|
||||
if (documentBody) {
|
||||
documentBody.style.removeProperty('overlow');
|
||||
}
|
||||
}
|
||||
|
||||
// show () {
|
||||
// this.setState({show: true});
|
||||
// }
|
||||
hide () {
|
||||
// 出场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
try {
|
||||
this.setState({ani: new Animated.Value(1), loading: false});
|
||||
ReactDOM.unmountComponentAtNode(oDiv);
|
||||
document.body.removeChild(oDiv);
|
||||
} catch (e) {}
|
||||
// 销毁
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="loading">
|
||||
<Animated.div style={{opacity: this.state.ani}} className="loading-wrapper">
|
||||
<div className="cmp-loading"></div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let oDiv = null;
|
||||
let loading = null;
|
||||
|
||||
Loading.show = () => {
|
||||
let props = {};
|
||||
let ele = document.querySelector('.zy-ui-loading');
|
||||
if (ele) return false;
|
||||
oDiv = document.createElement('div');
|
||||
oDiv.className = 'zy-ui-loading';
|
||||
document.body.appendChild(oDiv);
|
||||
ReactDOM.render(React.createElement(Loading, props), oDiv, function () {
|
||||
loading = this;
|
||||
});
|
||||
}
|
||||
|
||||
Loading.hide = () => {
|
||||
try {
|
||||
let ele = document.querySelector('.zy-ui-loading');
|
||||
if (ele) loading.hide();
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
export default Loading;
|
||||
16
src/components/Loading/index.js
Normal file
16
src/components/Loading/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import Loading from './Loading.jsx';
|
||||
|
||||
// Loading
|
||||
// 显示
|
||||
// Loading.show();
|
||||
// 隐藏
|
||||
// Loading.hide();
|
||||
|
||||
export default {
|
||||
show: () => {
|
||||
Loading.show();
|
||||
},
|
||||
hide: () => {
|
||||
Loading.hide();
|
||||
}
|
||||
};
|
||||
41
src/components/Loading/loading.scss
Normal file
41
src/components/Loading/loading.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
.loading {
|
||||
.loading-wrapper {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(white, .4);
|
||||
}
|
||||
$size: .8rem;
|
||||
.cmp-loading {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
// transform: translate(-50%, -50%);
|
||||
margin-left: -($size / 2);
|
||||
margin-top: -($size / 2);
|
||||
border-radius: 50%;
|
||||
width: $size;
|
||||
height: $size;
|
||||
border: .06rem solid $blue;
|
||||
border-top-color: $lightGray;
|
||||
border-bottom-color: $lightGray;
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
animation: dotRotate .7s infinite ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotRotate {
|
||||
from {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
48
src/components/Loading2/index.js
Normal file
48
src/components/Loading2/index.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import React, {Component} from 'react';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
import './loading.scss';
|
||||
|
||||
/*
|
||||
用法:
|
||||
// 显示
|
||||
this.refs.loading.show();
|
||||
// 隐藏
|
||||
this.refs.loading.hide();
|
||||
*/
|
||||
|
||||
class Loading extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
ani: new Animated.Value(1)
|
||||
}
|
||||
}
|
||||
show () {
|
||||
this.setState({show: true});
|
||||
}
|
||||
hide () {
|
||||
// 出场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false, ani: new Animated.Value(1)});
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="loading">
|
||||
{
|
||||
this.state.show && (
|
||||
<Animated.div style={{opacity: this.state.ani}} className="loading-wrapper">
|
||||
<div className="cmp-loading"></div>
|
||||
</Animated.div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Loading;
|
||||
41
src/components/Loading2/loading.scss
Normal file
41
src/components/Loading2/loading.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
.loading {
|
||||
.loading-wrapper {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(white, .4);
|
||||
}
|
||||
$size: .8rem;
|
||||
.cmp-loading {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
// transform: translate(-50%, -50%);
|
||||
margin-left: -($size / 2);
|
||||
margin-top: -($size / 2);
|
||||
border-radius: 50%;
|
||||
width: $size;
|
||||
height: $size;
|
||||
border: .06rem solid $blue;
|
||||
border-top-color: $lightGray;
|
||||
border-bottom-color: $lightGray;
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
animation: dotRotate .7s infinite ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotRotate {
|
||||
from {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
105
src/components/Promopt/index.js
Normal file
105
src/components/Promopt/index.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import React, {Component} from 'react';
|
||||
import './promopt.scss';
|
||||
|
||||
import Animated from 'animated/lib/targets/react-dom'
|
||||
|
||||
/*
|
||||
this.refs.dialog.show('', '成功注册!', {
|
||||
// showCancel: false,
|
||||
confirmText: '知道了'
|
||||
}, confirm => {
|
||||
console.log(confirm);
|
||||
});
|
||||
*/
|
||||
|
||||
class Prompt extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
title: '',
|
||||
options: {
|
||||
showCancel: true,
|
||||
cancelText: '',
|
||||
confirmText: ''
|
||||
},
|
||||
ani: new Animated.Value(0)
|
||||
}
|
||||
}
|
||||
async show (title, func) {
|
||||
this.setState({
|
||||
show: true,
|
||||
title
|
||||
});
|
||||
// if (options) this.setState({
|
||||
// 'options': {
|
||||
// ...this.state.options,
|
||||
// ...options
|
||||
// }
|
||||
// });
|
||||
if (func) this.func = func;
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 1,
|
||||
duration: 400
|
||||
}).start();
|
||||
}
|
||||
clickMask () {
|
||||
this.fnClose();
|
||||
}
|
||||
fnClose () {
|
||||
this.func && this.func(false);
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false});
|
||||
});
|
||||
}
|
||||
fnConfirm () {
|
||||
this.func && this.func(true);
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false});
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="promopt">
|
||||
{
|
||||
this.state.show && (
|
||||
<Animated.div className="mask" onClick={this.clickMask.bind(this)} style={{opacity: this.state.ani}}>
|
||||
<div className="dia-wrapper" onClick={e => e.stopPropagation()}>
|
||||
<div className="dia-head">
|
||||
{/* 标题 */}
|
||||
{
|
||||
this.state.title && (
|
||||
<div className="title">{this.state.title || '标题'}</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className="dia-body">
|
||||
{/* 内容 */}
|
||||
{this.props.children}
|
||||
</div>
|
||||
<div className="dia-footer">
|
||||
{/* 底部按钮 */}
|
||||
{
|
||||
this.state.options.showCancel && (
|
||||
<div className="btn btn-cancel" onClick={this.fnClose.bind(this)}>{this.state.options.cancelText || '取消'}</div>
|
||||
)
|
||||
}
|
||||
<div className="btn btn-confirm2" onClick={this.fnConfirm.bind(this)}>{this.state.options.confirmText || '确定'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Prompt;
|
||||
60
src/components/Promopt/promopt.scss
Normal file
60
src/components/Promopt/promopt.scss
Normal file
@@ -0,0 +1,60 @@
|
||||
@import '../../assets/style/colors.scss';
|
||||
// dialog 对话框
|
||||
.promopt {
|
||||
font-size: .32rem;
|
||||
.mask {
|
||||
position: fixed;
|
||||
z-index: 9000;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
background: rgba(black, .6);
|
||||
}
|
||||
.dia-wrapper {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
border-radius: .1rem;
|
||||
width: 4.5rem;
|
||||
}
|
||||
.dia-head {
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
padding: .2rem;
|
||||
color: $extraLightBlack;
|
||||
}
|
||||
.dia-body {
|
||||
padding: .2rem;
|
||||
text-align: center;
|
||||
font-size: .3rem;
|
||||
color: $black;
|
||||
}
|
||||
.dia-footer {
|
||||
display: flex;
|
||||
margin-top: .2rem;
|
||||
border-top: 1px solid $gray;
|
||||
align-items: center;
|
||||
}
|
||||
$btn-height: .8rem;
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: $btn-height;
|
||||
line-height: $btn-height;
|
||||
text-align: center;
|
||||
// width: 50%;
|
||||
}
|
||||
.btn:nth-of-type(2) {
|
||||
border-left: 1px solid $gray;
|
||||
}
|
||||
.btn-cancel {
|
||||
color: $sliver;
|
||||
}
|
||||
.btn-confirm2 {
|
||||
color: $blue;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
27
src/components/Test/Loading.jsx
Normal file
27
src/components/Test/Loading.jsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React, {Component} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './loading.scss';
|
||||
|
||||
export default class Loading extends Component {
|
||||
render () {
|
||||
let {tip} = this.props;
|
||||
console.log(tip);
|
||||
return (
|
||||
<div className="loading">
|
||||
<div className="loading-mask">
|
||||
<div className="wrapper">{tip}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Loading.show = function showLoading (options) {
|
||||
let props = options || {};
|
||||
let oDiv = document.createElement('div');
|
||||
document.body.appendChild(oDiv);
|
||||
ReactDOM.render(React.createElement(Loading, props), oDiv);
|
||||
}
|
||||
|
||||
// ReactDOM.unmountComponentAtNode(div);
|
||||
// document.body.removeChild(div);
|
||||
7
src/components/Test/index.js
Normal file
7
src/components/Test/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Loading from './Loading.jsx';
|
||||
|
||||
export default {
|
||||
open (tip = '加载中') {
|
||||
Loading.show({tip});
|
||||
}
|
||||
};
|
||||
18
src/components/Test/loading.scss
Normal file
18
src/components/Test/loading.scss
Normal file
@@ -0,0 +1,18 @@
|
||||
.loading {
|
||||
.loading-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(black, .6);
|
||||
z-index: 9999;
|
||||
}
|
||||
.wrapper {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
75
src/components/Toast/Toast.jsx
Normal file
75
src/components/Toast/Toast.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import React, {Component} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './toast.scss';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
|
||||
/*
|
||||
用法:
|
||||
Toast.show('aaa', [timer = 5s])
|
||||
*/
|
||||
|
||||
class Toast extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
text: '',
|
||||
ani: new Animated.Value(0)
|
||||
};
|
||||
this.timer = null;
|
||||
}
|
||||
componentDidMount () {
|
||||
this.show(this.props.text, this.props.timer);
|
||||
}
|
||||
async show (text, timer = 4) {
|
||||
// 清除定时器
|
||||
clearTimeout(this.timer);
|
||||
this.setState({
|
||||
text
|
||||
});
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 1,
|
||||
duration: 400
|
||||
}).start();
|
||||
this.timer = await setTimeout(() => {
|
||||
// 出场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({
|
||||
text: ''
|
||||
});
|
||||
ReactDOM.unmountComponentAtNode(oDiv[0]);
|
||||
document.body.removeChild(oDiv[0]);
|
||||
// console.log(oDiv);
|
||||
oDiv.shift();
|
||||
clearTimeout(this.timer);
|
||||
});
|
||||
}, timer * 1000);
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<Animated.div className="zy-toast" style={{opacity: this.state.ani}}>
|
||||
{this.state.text}
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let oDiv = [];
|
||||
|
||||
Toast.show = (text, timer) => {
|
||||
let props = {
|
||||
text, timer
|
||||
}
|
||||
let div = document.createElement('div');
|
||||
div.className = 'zy-ui-toast';
|
||||
document.body.appendChild(div);
|
||||
ReactDOM.render(React.createElement(Toast, props), div);
|
||||
oDiv.push(div);
|
||||
}
|
||||
|
||||
export default Toast;
|
||||
7
src/components/Toast/index.js
Normal file
7
src/components/Toast/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Toast from './Toast';
|
||||
|
||||
export default {
|
||||
show (text, timer) {
|
||||
Toast.show(text, timer);
|
||||
}
|
||||
};
|
||||
14
src/components/Toast/toast.scss
Normal file
14
src/components/Toast/toast.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.zy-toast {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-width: 5rem;
|
||||
font-size: .28rem;
|
||||
background: rgba(black, .6);
|
||||
padding: .2rem;
|
||||
color: white;
|
||||
border-radius: .1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
107
src/components/ddauth/Dialog.js
Normal file
107
src/components/ddauth/Dialog.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import React, {Component} from 'react';
|
||||
import './dialog.scss';
|
||||
|
||||
import Animated from 'animated/lib/targets/react-dom'
|
||||
|
||||
/*
|
||||
this.refs.dialog.show('', '成功注册!', {
|
||||
// showCancel: false,
|
||||
confirmText: '知道了'
|
||||
}, confirm => {
|
||||
console.log(confirm);
|
||||
});
|
||||
*/
|
||||
|
||||
class Dialog extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
options: {
|
||||
showCancel: true,
|
||||
cancelText: '',
|
||||
confirmText: ''
|
||||
},
|
||||
ani: new Animated.Value(0)
|
||||
}
|
||||
}
|
||||
async show (title, message, options, func) {
|
||||
this.setState({
|
||||
show: true,
|
||||
title,
|
||||
message
|
||||
});
|
||||
if (options) this.setState({
|
||||
'options': {
|
||||
...this.state.options,
|
||||
...options
|
||||
}
|
||||
});
|
||||
if (func) this.func = func;
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 1,
|
||||
duration: 400
|
||||
}).start();
|
||||
}
|
||||
clickMask () {
|
||||
this.fnClose();
|
||||
}
|
||||
fnClose () {
|
||||
this.func && this.func(false);
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false});
|
||||
});
|
||||
}
|
||||
fnConfirm () {
|
||||
this.func && this.func(true);
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({show: false});
|
||||
});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="dialog">
|
||||
{
|
||||
this.state.show && (
|
||||
<Animated.div className="mask" onClick={this.clickMask.bind(this)} style={{opacity: this.state.ani}}>
|
||||
<div className="dia-wrapper" onClick={e => e.stopPropagation()}>
|
||||
<div className="dia-head">
|
||||
{/* 标题 */}
|
||||
{
|
||||
this.state.title && (
|
||||
<div className="title">{this.state.title || '标题'}</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className="dia-body">
|
||||
{/* 内容 */}
|
||||
<div className="message">{this.state.message || '内容'}</div>
|
||||
</div>
|
||||
<div className="dia-footer">
|
||||
{/* 底部按钮 */}
|
||||
{
|
||||
this.state.options.showCancel && (
|
||||
<div className="btn btn-cancel" onClick={this.fnClose.bind(this)}>{this.state.options.cancelText || '取消'}</div>
|
||||
)
|
||||
}
|
||||
<div className="btn btn-confirm" onClick={this.fnConfirm.bind(this)}>{this.state.options.confirmText || '确定'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Dialog;
|
||||
132
src/components/ddauth/Form.js
Normal file
132
src/components/ddauth/Form.js
Normal file
@@ -0,0 +1,132 @@
|
||||
import React, { Component } from 'react';
|
||||
import './form.scss';
|
||||
import Toast from './Toast';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
|
||||
/*
|
||||
getFormData
|
||||
*/
|
||||
|
||||
class Form extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
list: {},
|
||||
focus: '',
|
||||
num: 0
|
||||
}
|
||||
}
|
||||
async componentDidMount () {
|
||||
for (let i = 0; i < this.props.fields.length; i++) {
|
||||
await this.setState({
|
||||
list: {
|
||||
...this.state.list,
|
||||
[this.props.fields[i].name]: this.props.fields[i].value
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// input focus
|
||||
fnFocus (name) {
|
||||
console.log(name);
|
||||
this.setState({focus: name});
|
||||
}
|
||||
fnBlur () {
|
||||
console.log('失去焦点');
|
||||
// this.setState({focus: ''});
|
||||
}
|
||||
// input 修改
|
||||
async fnChange (name, e) {
|
||||
// console.log(name, e.target.value);
|
||||
// this[name] = e.target.value;
|
||||
await this.setState({
|
||||
list: {
|
||||
...this.state.list,
|
||||
[name]: e.target.value
|
||||
}
|
||||
})
|
||||
// console.log(this.state);
|
||||
}
|
||||
// 清除
|
||||
fnClear (name) {
|
||||
// console.log('清除' + name);
|
||||
this.refs[name].value = '';
|
||||
this.setState({
|
||||
list: {
|
||||
...this.state.list,
|
||||
[name]: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获得formData
|
||||
getFormData () {
|
||||
// let form = new FormData(this.refs.form);
|
||||
let json = {};
|
||||
this.props.fields.forEach(field => {
|
||||
json[field.name] = this.refs[field.name].value;
|
||||
});
|
||||
|
||||
return json;
|
||||
}
|
||||
// 发送验证码
|
||||
async fnSendCode (name) {
|
||||
if (!/^\d{11}$/.test(this.state.list[name]) || this.state.num > 0) return false;
|
||||
let tel = this.state.list[name];
|
||||
console.log(tel);
|
||||
let form = new FormData();
|
||||
form.append('authID', tel);
|
||||
form.append('authToken', this.props.token);
|
||||
try {
|
||||
await fetchJson('/v2/auth2/SendVerifyCode', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
this.refs.toast.show('短信发送成功');
|
||||
// 开始倒计时
|
||||
await this.setState({num: 59});
|
||||
clearInterval(this.timer);
|
||||
this.timer = setInterval(() => {
|
||||
if (this.state.num === 0) {
|
||||
clearInterval(this.timer);
|
||||
} else {
|
||||
this.setState({num: --this.state.num});
|
||||
}
|
||||
}, 1000);
|
||||
} catch (e) {
|
||||
this.refs.toast.show(e);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
if (!this.props.fields) console.error('Form need fields');
|
||||
return (
|
||||
<form ref="form" className="form">
|
||||
{
|
||||
this.props.fields.length > 0 && (
|
||||
this.props.fields.map((field, index) => (
|
||||
<div className="form-item" key={index}>
|
||||
<label className={'icon ' + field.icon} htmlFor={field.name}></label>
|
||||
<input ref={field.name} type={field.name} placeholder={field.placeholder} name={field.name} id={field.name} defaultValue={field.value} onChange={this.fnChange.bind(this, field.name)} onFocus={this.fnFocus.bind(this, field.name)} onBlur={this.fnBlur.bind(this)}/>
|
||||
{/* // 清空按钮 */}
|
||||
{
|
||||
(this.state.focus === field.name && this.state.list[field.name]) && (
|
||||
<div className="clear" onClick={this.fnClear.bind(this, field.name)}></div>
|
||||
)
|
||||
}
|
||||
{/* // 其他按钮 */}
|
||||
{
|
||||
field.btn && (
|
||||
<div className={this.state.list[field.name] && this.state.list[field.name].length === 11 && this.state.num === 0 ? 'btn-getcode' : 'btn-getcode disabled'} onClick={this.fnSendCode.bind(this, field.name)}>{field.btn.name}{this.state.num > 0 && '(' + this.state.num + ')'}</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
))
|
||||
)
|
||||
}
|
||||
<Toast ref="toast"></Toast>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Form;
|
||||
61
src/components/ddauth/Toast.js
Normal file
61
src/components/ddauth/Toast.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import React, {Component} from 'react';
|
||||
import './toast.scss';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
|
||||
/*
|
||||
用法:
|
||||
this.refs.xxx.show('aaa', [timer = 5s])
|
||||
*/
|
||||
|
||||
class Toast extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
text: '',
|
||||
ani: new Animated.Value(0)
|
||||
};
|
||||
this.timer = null;
|
||||
}
|
||||
async show (text, timer = 5) {
|
||||
// 清除定时器
|
||||
clearTimeout(this.timer);
|
||||
this.setState({
|
||||
show: true,
|
||||
text
|
||||
});
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 1,
|
||||
duration: 400
|
||||
}).start();
|
||||
this.timer = await setTimeout(() => {
|
||||
// 出场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 400
|
||||
}).start(() => {
|
||||
this.setState({
|
||||
show: false,
|
||||
text: ''
|
||||
});
|
||||
clearTimeout(this.timer);
|
||||
});
|
||||
}, timer * 1000);
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.state.show && (
|
||||
<Animated.div className="zy-toast" style={{opacity: this.state.ani}}>
|
||||
{this.state.text}
|
||||
</Animated.div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Toast;
|
||||
60
src/components/ddauth/dialog.scss
Normal file
60
src/components/ddauth/dialog.scss
Normal file
@@ -0,0 +1,60 @@
|
||||
$maincolor: #409EFF;
|
||||
// dialog 对话框
|
||||
.dialog {
|
||||
font-size: .32rem;
|
||||
.mask {
|
||||
position: fixed;
|
||||
z-index: 9000;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
background: rgba(black, .6);
|
||||
}
|
||||
.dia-wrapper {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
border-radius: .1rem;
|
||||
width: 4.5rem;
|
||||
}
|
||||
.dia-head {
|
||||
// border-bottom: 1px solid $maincolor;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
padding: .2rem;
|
||||
color: #303133;
|
||||
}
|
||||
.dia-body {
|
||||
padding: .2rem;
|
||||
text-align: center;
|
||||
font-size: .3rem;
|
||||
color: #606266;
|
||||
}
|
||||
.dia-footer {
|
||||
display: flex;
|
||||
margin-top: .2rem;
|
||||
border-top: 1px solid #ccc;
|
||||
align-items: center;
|
||||
}
|
||||
$btn-height: .8rem;
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: $btn-height;
|
||||
line-height: $btn-height;
|
||||
text-align: center;
|
||||
}
|
||||
.btn:nth-of-type(2) {
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
.btn-cancel {
|
||||
color: #909399;
|
||||
}
|
||||
.btn-confirm {
|
||||
color: $maincolor;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
71
src/components/ddauth/form.scss
Normal file
71
src/components/ddauth/form.scss
Normal file
@@ -0,0 +1,71 @@
|
||||
// 表单样式
|
||||
$maincolor: #409EFF;
|
||||
.form {
|
||||
.form-item {
|
||||
font-size: .3rem;
|
||||
box-sizing: border-box;
|
||||
height: 1rem;
|
||||
padding: .2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: white;
|
||||
border-bottom: 1px solid #ccc;
|
||||
position: relative;
|
||||
}
|
||||
.icon {
|
||||
display: inline-block;
|
||||
width: .36rem;
|
||||
height: .36rem;
|
||||
// border: 1px solid;
|
||||
background-size: 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: .2rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.icon-username {
|
||||
background-image: url(../../assets/imgs/icon-username.png);
|
||||
}
|
||||
.icon-nickname {
|
||||
background-image: url(../../assets/imgs/icon-nickname2.png);
|
||||
}
|
||||
.icon-tel {
|
||||
background-image: url(../../assets/imgs/icon-tel.png);
|
||||
}
|
||||
.icon-code {
|
||||
background-image: url(../../assets/imgs/icon-code.png);
|
||||
}
|
||||
input {
|
||||
color: #333;
|
||||
// padding: .1rem;
|
||||
height: .6rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
// color: black;
|
||||
color: #ccc;
|
||||
}
|
||||
.clear {
|
||||
// position: absolute;
|
||||
background: url(../../assets/imgs/icon-clear.png) center center no-repeat;
|
||||
width: .8rem;
|
||||
height: .7rem;
|
||||
// top: 50%;
|
||||
// right: 0;
|
||||
// transform: translateY(-50%);
|
||||
background-size: .36rem;
|
||||
}
|
||||
.btn-getcode {
|
||||
background: $maincolor;
|
||||
color: white;
|
||||
padding: .1rem .2rem;
|
||||
border-radius: .1rem;
|
||||
white-space: nowrap;
|
||||
margin-left: .2rem;
|
||||
}
|
||||
.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
14
src/components/ddauth/toast.scss
Normal file
14
src/components/ddauth/toast.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.zy-toast {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-width: 5rem;
|
||||
font-size: .28rem;
|
||||
background: rgba(black, .6);
|
||||
padding: .2rem;
|
||||
color: white;
|
||||
border-radius: .1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
71
src/components/form.scss
Normal file
71
src/components/form.scss
Normal file
@@ -0,0 +1,71 @@
|
||||
// 表单样式
|
||||
$maincolor: #409EFF;
|
||||
.form {
|
||||
.form-item {
|
||||
font-size: .3rem;
|
||||
box-sizing: border-box;
|
||||
height: 1rem;
|
||||
padding: .2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: white;
|
||||
border-bottom: 1px solid #ccc;
|
||||
position: relative;
|
||||
}
|
||||
.icon {
|
||||
display: inline-block;
|
||||
width: .36rem;
|
||||
height: .36rem;
|
||||
// border: 1px solid;
|
||||
background-size: 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: .2rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.icon-username {
|
||||
background-image: url(../assets/imgs/icon-username.png);
|
||||
}
|
||||
.icon-nickname {
|
||||
background-image: url(../assets/imgs/icon-nickname2.png);
|
||||
}
|
||||
.icon-tel {
|
||||
background-image: url(../assets/imgs/icon-tel.png);
|
||||
}
|
||||
.icon-code {
|
||||
background-image: url(../assets/imgs/icon-code.png);
|
||||
}
|
||||
input {
|
||||
color: #333;
|
||||
// padding: .1rem;
|
||||
height: .6rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
// color: black;
|
||||
color: #ccc;
|
||||
}
|
||||
.clear {
|
||||
// position: absolute;
|
||||
background: url(../assets/imgs/icon-clear.png) center center no-repeat;
|
||||
width: .8rem;
|
||||
height: .7rem;
|
||||
// top: 50%;
|
||||
// right: 0;
|
||||
// transform: translateY(-50%);
|
||||
background-size: .36rem;
|
||||
}
|
||||
.btn-getcode {
|
||||
background: $maincolor;
|
||||
color: white;
|
||||
padding: .1rem .2rem;
|
||||
border-radius: .1rem;
|
||||
white-space: nowrap;
|
||||
margin-left: .2rem;
|
||||
}
|
||||
.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
40
src/components/layout/CheckBox.js
Normal file
40
src/components/layout/CheckBox.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './main.scss';
|
||||
|
||||
/*
|
||||
current={[]} [-1, 0, 1]
|
||||
fields={[
|
||||
{value: 1, text: '营业中'},
|
||||
{value: 0, text: '休息中'},
|
||||
{value: -1, text: '禁用中'}
|
||||
]}
|
||||
fnClick={this.changeStatuss.bind(this)} changeStatuss(val)
|
||||
*/
|
||||
|
||||
class CheckBox extends Component {
|
||||
fnClick (val) {
|
||||
// console.log(val);
|
||||
this.props.fnClick && this.props.fnClick(val);
|
||||
}
|
||||
render() {
|
||||
let fields = this.props.fields || [];
|
||||
let current = this.props.current || [];
|
||||
return (
|
||||
<div className="zy-ui-checkbox">
|
||||
{
|
||||
fields.map((field, index) => (
|
||||
<div
|
||||
className={classNames('zy-ui-checkbox-btn', {'zy-ui-checkbox-btn-active': current.indexOf(field.value) !== -1})}
|
||||
key={index}
|
||||
onClick={this.fnClick.bind(this, field.value)}
|
||||
>{field.text}</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CheckBox;
|
||||
37
src/components/layout/CheckBoxSelf.js
Normal file
37
src/components/layout/CheckBoxSelf.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './main.scss';
|
||||
|
||||
/*
|
||||
current={[]} [-1, 0, 1]
|
||||
fields={[
|
||||
{value: 1, text: '营业中'},
|
||||
{value: 0, text: '休息中'},
|
||||
{value: -1, text: '禁用中'}
|
||||
]}
|
||||
fnClick={this.changeStatuss.bind(this)} changeStatuss(val)
|
||||
*/
|
||||
|
||||
class CheckBoxSelf extends Component {
|
||||
fnClick (val) {
|
||||
// console.log(val);
|
||||
this.props.fnClick && this.props.fnClick(val);
|
||||
}
|
||||
render() {
|
||||
let fields = this.props.fields || [];
|
||||
let current = this.props.current || null;
|
||||
return (
|
||||
<div className="zy-ui-checkbox">
|
||||
<div
|
||||
className={classNames('zy-ui-checkbox-btn', {'zy-ui-checkbox-btn-active': current === fields[1]}, this.props.className)}
|
||||
onClick={this.fnClick.bind(this, current === fields[1] ? fields[0] : fields[1])}
|
||||
>
|
||||
<span className={classNames({'zy-ui-checkbox-check-true': current === fields[1]}, {'zy-ui-checkbox-check-false': current !== fields[1]})}></span>{this.props.text}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CheckBoxSelf;
|
||||
113
src/components/layout/CheckList.js
Normal file
113
src/components/layout/CheckList.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
import classNames from 'classnames';
|
||||
import BScroll from 'better-scroll';
|
||||
import './main.scss';
|
||||
const clientH = document.documentElement.clientHeight;
|
||||
/*
|
||||
ref="checklist"
|
||||
datas={this.props.system.cityLevel2}
|
||||
nullShow = false 是否显示空
|
||||
nullLabel = '' null显示
|
||||
map={{value: 'code', label: 'name'}}
|
||||
current={storeSearch.placeID}
|
||||
title="城市选择"
|
||||
fnPick={this.cityPick.bind(this)}
|
||||
|
||||
// 打开
|
||||
this.refs.xxx.show()
|
||||
*/
|
||||
|
||||
class CheckList extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
ani: new Animated.Value(clientH)
|
||||
};
|
||||
this.scroll = null;
|
||||
}
|
||||
componentDidMount () {
|
||||
|
||||
}
|
||||
componentDidUpdate () {
|
||||
if (this.scroll) {
|
||||
this.scroll.refresh();
|
||||
this.scroll.scrollTo(0, 0);
|
||||
} else {
|
||||
if (this.refs.bodyWrapper) {
|
||||
this.scroll = new BScroll(this.refs.bodyWrapper, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// show
|
||||
show () {
|
||||
// console.log(this)
|
||||
this.setState({show: true});
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 300
|
||||
}).start(() => {
|
||||
console.log('start')
|
||||
});
|
||||
}
|
||||
hide () {
|
||||
this.setState({show: false, ani: new Animated.Value(clientH)});
|
||||
this.scroll = null;
|
||||
}
|
||||
// 返回
|
||||
fnReturn () {
|
||||
console.log('返回');
|
||||
this.hide();
|
||||
}
|
||||
// 选取
|
||||
fnClick (code) {
|
||||
// console.log(code);
|
||||
this.props.fnPick && this.props.fnPick(code);
|
||||
this.hide()
|
||||
}
|
||||
render() {
|
||||
return ReactDOM.createPortal((
|
||||
<div className={classNames("zy-ui-checklist", {'pointerAll': this.state.show})}>
|
||||
{
|
||||
this.state.show && (
|
||||
<div className="zy-ui-checklist-mask" onClick={this.hide.bind(this)}>
|
||||
<Animated.div className="zy-ui-checklist-wrapper" style={{transform: [{translateY: this.state.ani}]}} onClick={e => e.stopPropagation()}>
|
||||
<div className="zy-ui-checklist-header">
|
||||
<div className="zy-ui-checklist-return" onClick={this.fnReturn.bind(this)}>返回</div>
|
||||
<div className="zy-ui-checklist-title">{this.props.title}</div>
|
||||
</div>
|
||||
{/*onTouchMove={this.fnTouchMove.bind(this)} */}
|
||||
<div className="zy-ui-checklist-body" ref="bodyWrapper">
|
||||
<div>
|
||||
{
|
||||
this.props.nullShow && (
|
||||
<div className={classNames('zy-ui-checklist-item', {'zy-ui-checklist-item-active': !this.props.current})} onClick={this.fnClick.bind(this, null)}>{this.props.nullLabel}</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
this.props.datas.length > 0 && this.props.datas.map((data, index) => (
|
||||
<div key={index} className={classNames('zy-ui-checklist-item', {'zy-ui-checklist-item-active': this.props.current === data[this.props.map.value]})} onClick={this.fnClick.bind(this, data[this.props.map.value])}>{data[this.props.map.label]}</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
), document.getElementById('root'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CheckList;
|
||||
38
src/components/layout/KeyWordSearch.js
Normal file
38
src/components/layout/KeyWordSearch.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react';
|
||||
import './main.scss';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import SearchStore from './SearchStore';
|
||||
|
||||
class KeyWordSearch extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
name: '',
|
||||
id: null
|
||||
};
|
||||
}
|
||||
showPick = () => {
|
||||
this.refs.storePick.show();
|
||||
}
|
||||
pickStore = async (val) => {
|
||||
// console.log(val);
|
||||
let {id, name} = val;
|
||||
await this.setState({
|
||||
name: `${name}-${id}`,
|
||||
id
|
||||
});
|
||||
this.props.fnPick && this.props.fnPick(id);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="zy-ui-keywordsearch">
|
||||
<div className={classNames('placeholder', {'name': this.state.name})} onClick={this.showPick}>{this.state.name ? this.state.name : this.props.placeholder}</div>
|
||||
<SearchStore ref="storePick" fnPick={this.pickStore}></SearchStore>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default KeyWordSearch;
|
||||
60
src/components/layout/PickInput.js
Normal file
60
src/components/layout/PickInput.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import React, {Component} from 'react';
|
||||
import './main.scss';
|
||||
import ReactSVG from 'react-svg';
|
||||
|
||||
import CheckList from '@/components/layout/CheckList';
|
||||
import SVGDown from '@/assets/svg/icon-down.svg';
|
||||
|
||||
class PickInput extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {};
|
||||
}
|
||||
// 选取后
|
||||
fnPick (val) {
|
||||
// console.log(val);
|
||||
this.props.fnPick && this.props.fnPick(val);
|
||||
}
|
||||
// 弹出选择窗口
|
||||
showList () {
|
||||
this.refs.checklist.show();
|
||||
}
|
||||
// 输入框改变
|
||||
fnChange = e => {
|
||||
// console.log(e.target.value);
|
||||
this.props.fnChange && this.props.fnChange(e.target.value);
|
||||
}
|
||||
// 选取输入框
|
||||
render () {
|
||||
// 显示文字
|
||||
let text = this.props.datas.find(item => item[this.props.map['value']] === this.props.current);
|
||||
return (
|
||||
<div className="zy-ui-pick-input">
|
||||
{/* 选择框 */}
|
||||
<div className="zy-ui-pick-btn" onClick={this.showList.bind(this)}>
|
||||
<span className="zy-ui-pick-text">{text[this.props.map['label']]}</span>
|
||||
<ReactSVG className="zy-ui-pick-icon" src={SVGDown}></ReactSVG>
|
||||
</div>
|
||||
{/* 输入框 */}
|
||||
<input className="zy-ui-pick-cmpinput" placeholder={this.props.placeholder} type={this.props.type || 'text'} onChange={this.fnChange}/>
|
||||
{/* 操作按钮 */}
|
||||
{
|
||||
this.props.fnConfirm && (
|
||||
<div className="zy-ui-pick-confirmbtn" onClick={() => {this.props.fnConfirm()}}>获取</div>
|
||||
)
|
||||
}
|
||||
{/* 弹出窗口 */}
|
||||
<CheckList
|
||||
ref="checklist"
|
||||
title={this.props.title}
|
||||
datas={this.props.datas}
|
||||
map={this.props.map}
|
||||
current={this.props.current}
|
||||
fnPick={this.fnPick.bind(this)}
|
||||
></CheckList>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PickInput;
|
||||
145
src/components/layout/PopupPage.js
Normal file
145
src/components/layout/PopupPage.js
Normal file
@@ -0,0 +1,145 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './main.scss';
|
||||
import ReactSVG from 'react-svg';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
import classNames from 'classnames';
|
||||
import BScroll from 'better-scroll';
|
||||
|
||||
import SVGReturn from '@/assets/svg/icon-return.svg';
|
||||
// import SVGConfirm from '@/assets/svg/icon-confirm.svg';
|
||||
|
||||
const screenW = document.body.clientWidth;
|
||||
|
||||
/*
|
||||
title="更多检索条件"
|
||||
fnReturn={this.props.fnReturn.bind(this)}
|
||||
fnPrevConfirm={fn} ruturn true or false 确认前
|
||||
fnConfirm={this.props.fnConfirm.bind(this)}
|
||||
*/
|
||||
|
||||
class PopupPage extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
ani: new Animated.Value(screenW)
|
||||
};
|
||||
this.isMain = !this.props.fnReturn && !this.props.fnConfirm;
|
||||
this.scroll = null;
|
||||
}
|
||||
componentDidMount () {
|
||||
// 入场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 300
|
||||
}).start(() => {
|
||||
// 增加滚动
|
||||
// this.scroll = new BScroll(this.refs.toBottom, {
|
||||
// click: true,
|
||||
// stopPropagation: true,
|
||||
// bounce: {
|
||||
// top: false,
|
||||
// bottom: false
|
||||
// }
|
||||
// })
|
||||
});
|
||||
}
|
||||
componentDidUpdate () {
|
||||
if (this.scroll) {
|
||||
this.scroll.refresh();
|
||||
} else {
|
||||
if (this.refs.toBottom) {
|
||||
this.scroll = new BScroll(this.refs.toBottom, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回按钮
|
||||
fnReturn () {
|
||||
// 出场动画
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: -screenW,
|
||||
duration: 300
|
||||
}).start(() => {
|
||||
this.props.fnReturn();
|
||||
});
|
||||
}
|
||||
// 确认按钮
|
||||
async fnConfirm () {
|
||||
if (this.props.fnPrevConfirm) {
|
||||
let res = await this.props.fnPrevConfirm();
|
||||
if (res) {
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: -screenW,
|
||||
duration: 300
|
||||
}).start(() => {
|
||||
this.props.fnConfirm();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: -screenW,
|
||||
duration: 300
|
||||
}).start(() => {
|
||||
this.props.fnConfirm();
|
||||
});
|
||||
}
|
||||
}
|
||||
// 滚动到底部
|
||||
toBottom () {
|
||||
// console.log()
|
||||
// this.refs.toBottom.scrollTop = 100;
|
||||
}
|
||||
fnTouchMove (e) {
|
||||
console.log(e);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
render() {
|
||||
return ReactDOM.createPortal((
|
||||
<div className="popup-page">
|
||||
<Animated.div className={classNames('popup-wrapper', {'popup-wrapper-main': this.isMain})} style={{transform: [{translateX: this.state.ani}]}}>
|
||||
<div className={classNames('popup-menu', {'menu-center': this.isMain})}>
|
||||
{/* 返回按钮 */}
|
||||
{
|
||||
this.props.fnReturn && (
|
||||
<div className="btn-return" onClick={this.fnReturn.bind(this)}>
|
||||
<ReactSVG className="icon" src={SVGReturn}></ReactSVG>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className="popup-title">
|
||||
{
|
||||
this.props.SVG && <ReactSVG src={this.props.SVG} className="svg"></ReactSVG>
|
||||
}
|
||||
{this.props.title}
|
||||
</div>
|
||||
{/* 确定按钮 */}
|
||||
{
|
||||
this.props.fnConfirm && (
|
||||
<div className="btn-confirm" onClick={this.fnConfirm.bind(this)}>
|
||||
{/* <ReactSVG className="icon" src={SVGConfirm}></ReactSVG> */}
|
||||
<span className="btn-confirm-text">确定</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className={classNames('popup-content', {'popup-content-main': this.isMain}, this.props.className)} ref="toBottom">
|
||||
<div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
), document.getElementById('root'));
|
||||
}
|
||||
}
|
||||
|
||||
export default PopupPage;
|
||||
81
src/components/layout/PopupPage2.js
Normal file
81
src/components/layout/PopupPage2.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React, { Component } from 'react';
|
||||
import './main.scss';
|
||||
import ReactSVG from 'react-svg'
|
||||
import classNames from 'classnames';
|
||||
|
||||
import SVGReturn from '@/assets/svg/icon-return.svg';
|
||||
// import SVGConfirm from '@/assets/svg/icon-confirm.svg';
|
||||
|
||||
/*
|
||||
title="更多检索条件"
|
||||
fnReturn={this.props.fnReturn.bind(this)}
|
||||
fnPrevConfirm={fn} ruturn true or false 确认前
|
||||
fnConfirm={this.props.fnConfirm.bind(this)}
|
||||
*/
|
||||
|
||||
class PopupPage extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {};
|
||||
this.isMain = !this.props.fnReturn && !this.props.fnConfirm;
|
||||
}
|
||||
// 返回按钮
|
||||
fnReturn () {
|
||||
this.props.fnReturn();
|
||||
}
|
||||
// 确认按钮
|
||||
async fnConfirm () {
|
||||
if (this.props.fnPrevConfirm) {
|
||||
let res = await this.props.fnPrevConfirm();
|
||||
if (res) {
|
||||
this.props.fnConfirm();
|
||||
}
|
||||
} else {
|
||||
this.props.fnConfirm();
|
||||
}
|
||||
}
|
||||
// 滚动到底部
|
||||
toBottom () {
|
||||
// console.log()
|
||||
// this.refs.toBottom.scrollTop = 100;
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="popup-page2">
|
||||
<div className={classNames('popup-wrapper', {'popup-wrapper-main': this.isMain})}>
|
||||
<div className={classNames('popup-menu', {'menu-center': this.isMain})}>
|
||||
{/* 返回按钮 */}
|
||||
{
|
||||
this.props.fnReturn && (
|
||||
<div className="btn-return" onClick={this.fnReturn.bind(this)}>
|
||||
<ReactSVG className="icon" src={SVGReturn}></ReactSVG>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className="popup-title">
|
||||
{
|
||||
this.props.SVG && <ReactSVG src={this.props.SVG} className="svg"></ReactSVG>
|
||||
}
|
||||
{this.props.title}
|
||||
</div>
|
||||
{/* 确定按钮 */}
|
||||
{
|
||||
this.props.fnConfirm && (
|
||||
<div className="btn-confirm" onClick={this.fnConfirm.bind(this)}>
|
||||
{/* <ReactSVG className="icon" src={SVGConfirm}></ReactSVG> */}
|
||||
<span className="btn-confirm-text">确定</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className={classNames('popup-content', {'popup-content-main': this.isMain})} ref="toBottom">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PopupPage;
|
||||
36
src/components/layout/Radio.js
Normal file
36
src/components/layout/Radio.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './main.scss';
|
||||
|
||||
// 单选组件
|
||||
/*
|
||||
fields={[
|
||||
{value: 0, text: '不限定'},
|
||||
{value: 1, text: '已绑定'},
|
||||
{value: -1, text: '未绑定'}
|
||||
]}
|
||||
id={}
|
||||
current={storeSearch.vendorStoreConds['0']}
|
||||
fnClick={} return val id
|
||||
*/
|
||||
|
||||
class Radio extends Component {
|
||||
fnClick (val) {
|
||||
// console.log(val);
|
||||
this.props.fnClick && this.props.fnClick(val, this.props.id);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="zy-ui-radio">
|
||||
{
|
||||
this.props.fields && this.props.fields.map((field, index) => (
|
||||
<div key={index} className={classNames('zy-ui-radio-btn', {'zy-ui-radio-btn-active': field.value === this.props.current})} onClick={this.fnClick.bind(this, field.value)}>{field.text}</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Radio;
|
||||
237
src/components/layout/SearchAddress.js
Normal file
237
src/components/layout/SearchAddress.js
Normal file
@@ -0,0 +1,237 @@
|
||||
import React, { Component } from 'react';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
import fetchJsonp from 'fetch-jsonp';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import './main.scss';
|
||||
import classNames from 'classnames';
|
||||
import BScroll from 'better-scroll';
|
||||
import * as dd from 'dingtalk-jsapi';
|
||||
|
||||
import Loading from '@/components/Loading';
|
||||
import ReactSVG from 'react-svg'
|
||||
import SVGAddress from '@/assets/svg/icon-address.svg';
|
||||
import SVGAddressList from '@/assets/svg/icon-addresslist.svg';
|
||||
import SVGMYPOSITION from '@/assets/svg/icon-curposition.svg';
|
||||
|
||||
const clientH = document.documentElement.clientHeight;
|
||||
/*
|
||||
region 市名
|
||||
ref="SearchAddress"
|
||||
fnPick={this.fn.bind(this)}
|
||||
|
||||
// 打开
|
||||
this.refs.xxx.show()
|
||||
*/
|
||||
|
||||
class SearchAddress extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
ani: new Animated.Value(clientH),
|
||||
keyword: '',
|
||||
addressList: [],
|
||||
lat: '',
|
||||
lng: ''
|
||||
};
|
||||
this.scroll = null;
|
||||
}
|
||||
async componentDidMount () {
|
||||
console.log('地图 mounted');
|
||||
await this.getAddress();
|
||||
}
|
||||
componentDidUpdate () {
|
||||
console.log('update');
|
||||
if (this.scroll) {
|
||||
this.scroll.refresh();
|
||||
this.scroll.scrollTo(0, 0);
|
||||
} else {
|
||||
if (this.refs.scrollList) {
|
||||
this.scroll = new BScroll(this.refs.scrollList, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
async posiAddress () {
|
||||
let {result} = await (await fetchJsonp(`https://apis.map.qq.com/ws/geocoder/v1/?output=jsonp&key=ZGGBZ-RUWLQ-XY25J-GD2AV-YPT2T-6EFA6&location=${this.state.lat},${this.state.lng}&get_poi=1`)).json()
|
||||
// console.log('datasdfdsfdsfd', result);
|
||||
if (result) {
|
||||
this.setState({addressList: result.pois});
|
||||
}
|
||||
}
|
||||
// 腾讯地图查找地址关键字
|
||||
async getAddress () {
|
||||
// let {data} = await (await fetchJsonp(`https://apis.map.qq.com/ws/place/v1/suggestion/?output=jsonp&key=ZGGBZ-RUWLQ-XY25J-GD2AV-YPT2T-6EFA6&keyword=${this.state.keyword}®ion=${this.props.region}&policy=1®ion_fix=1`)).json()
|
||||
let {data} = await (await fetchJsonp(`https://apis.map.qq.com/ws/place/v1/search/?output=jsonp&key=ZGGBZ-RUWLQ-XY25J-GD2AV-YPT2T-6EFA6&keyword=${encodeURI(this.state.keyword)}&boundary=region(${this.props.region},0)`)).json()
|
||||
if (data) {
|
||||
this.setState({addressList: data});
|
||||
}
|
||||
// address: "四川省成都市青羊区童子街50号"
|
||||
// location: {lat, lng}
|
||||
// title: '童子街'
|
||||
}
|
||||
// 输入关键词
|
||||
async handleKeyword (e) {
|
||||
await this.setState({keyword: e.target.value});
|
||||
await this.getAddress(this.state.keyword);
|
||||
}
|
||||
// show
|
||||
async show () {
|
||||
await this.setState({show: true});
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 300
|
||||
}).start();
|
||||
this.refs.scrollList.addEventListener('scroll', this.handleBlur.bind(this));
|
||||
// if (dd.ios || dd.android) {
|
||||
// dd.device.geolocation.get({
|
||||
// targetAccuracy: 200,
|
||||
// coordinate: 1,
|
||||
// onSuccess: res => {
|
||||
// let {longitude, latitude} = res;
|
||||
// this.setState({
|
||||
// lat: latitude,
|
||||
// lng: longitude
|
||||
// });
|
||||
// },
|
||||
// onFail: err => {
|
||||
// this.setState({
|
||||
// lat: JSON.stringify(err)
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
hide () {
|
||||
this.setState({show: false, ani: new Animated.Value(clientH)});
|
||||
this.refs.scrollList.removeEventListener('scroll', this.handleBlur.bind(this));
|
||||
this.scroll = null;
|
||||
}
|
||||
// 滚动失去焦点
|
||||
handleBlur () {
|
||||
this.refs.keyword.blur();
|
||||
}
|
||||
// 选取地址
|
||||
fnClick (address) {
|
||||
// console.log(address);
|
||||
this.props.fnPick && this.props.fnPick(address);
|
||||
this.hide();
|
||||
}
|
||||
// 返回
|
||||
fnReturn () {
|
||||
console.log('返回');
|
||||
this.hide();
|
||||
}
|
||||
// 获取当前定位
|
||||
async getCurPosition () {
|
||||
// 清除关键字,失去焦点
|
||||
this.refs.keyword.value = '';
|
||||
this.setState({keyword: ''});
|
||||
this.refs.keyword.blur();
|
||||
console.log('获取当前定位');
|
||||
let config = {
|
||||
agentId: process.env.NODE_ENV !== 'production' ? '241047291' : '239461075', // 241047291 239461075
|
||||
corpId: 'ding7ab5687f3784a8db',
|
||||
timeStamp: Math.round(new Date().getTime() / 1000),
|
||||
nonceStr: 'rosy' + new Date().getTime(),
|
||||
signature: '', // 接口获取
|
||||
jsApiList: ['device.geolocation.get']
|
||||
}
|
||||
const url = window.location.origin + window.location.pathname;
|
||||
console.log(config);
|
||||
|
||||
// 通过京西接口后去signature
|
||||
let signature = await fetchJson(`/v2/ddapi/Sign?url=${url}&nonceStr=${config.nonceStr}&timeStamp=${config.timeStamp}`);
|
||||
console.log('signature', signature);
|
||||
config.signature = signature;
|
||||
// 通过接口获取鉴权
|
||||
if (dd.ios || dd.android) {
|
||||
dd.ready(() => {
|
||||
dd.config({
|
||||
...config,
|
||||
});
|
||||
dd.ready(() => {
|
||||
Loading.show();
|
||||
dd.device.geolocation.get({
|
||||
targetAccuracy: 200,
|
||||
coordinate: 1,
|
||||
onSuccess: async res => {
|
||||
let {longitude, latitude} = res;
|
||||
await this.setState({
|
||||
lat: latitude,
|
||||
lng: longitude
|
||||
});
|
||||
// 通过经纬度获取地址列表
|
||||
await this.posiAddress();
|
||||
Loading.hide();
|
||||
},
|
||||
onFail: err => {
|
||||
console.log(JSON.stringify(err));
|
||||
dd.device.notification.alert({
|
||||
message: JSON.stringify(err),
|
||||
title: '错误'
|
||||
})
|
||||
Loading.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
dd.error(err => {
|
||||
console.log(JSON.stringify(err));
|
||||
dd.device.notification.alert({
|
||||
message: JSON.stringify(err),
|
||||
title: '错误'
|
||||
})
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={classNames("zy-ui-checklist search-address", {'pointerAll': this.state.show})}>
|
||||
{
|
||||
this.state.show && (
|
||||
<div className="zy-ui-checklist-mask" onClick={this.hide.bind(this)}>
|
||||
<Animated.div className="zy-ui-checklist-wrapper" style={{transform: [{translateY: this.state.ani}]}} onClick={e => e.stopPropagation()}>
|
||||
<div className="zy-ui-address-header">
|
||||
<div className="zy-ui-checklist-return" onClick={this.fnReturn.bind(this)}>返回</div>
|
||||
<div className="zy-ui-address-input">
|
||||
<input ref="keyword" type="text" onChange={this.handleKeyword.bind(this)} placeholder="请输入详细地址进行检索"/>
|
||||
<ReactSVG className="svg" src={SVGAddress}></ReactSVG>
|
||||
</div>
|
||||
<div className="zy-ui-checklist-position" onClick={this.getCurPosition.bind(this)}>
|
||||
<ReactSVG className="my-position" src={SVGMYPOSITION}></ReactSVG>
|
||||
</div>
|
||||
</div>
|
||||
<div className="zy-ui-address-body" ref="scrollList">
|
||||
<div>
|
||||
{
|
||||
this.state.addressList.length > 0 && this.state.addressList.map(address => (
|
||||
<div className="address-item" key={address.id} onClick={this.fnClick.bind(this, address)}>
|
||||
<ReactSVG className="svg" src={SVGAddressList}></ReactSVG>
|
||||
<div className="address-content">
|
||||
<div className="content1">{address.title}</div>
|
||||
<div className="content2">{address.address}</div>
|
||||
</div>
|
||||
<div className="pick-text">选择</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SearchAddress;
|
||||
161
src/components/layout/SearchStore.js
Normal file
161
src/components/layout/SearchStore.js
Normal file
@@ -0,0 +1,161 @@
|
||||
import React, { Component } from 'react';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import BScroll from 'better-scroll';
|
||||
import './main.scss';
|
||||
import classNames from 'classnames';
|
||||
import {debounce} from '@/utils'
|
||||
|
||||
import ReactSVG from 'react-svg'
|
||||
import SVGAddress from '@/assets/svg/icon-store.svg';
|
||||
// import SVGAddressList from '@/assets/svg/icon-addresslist.svg';
|
||||
|
||||
const clientH = document.documentElement.clientHeight;
|
||||
/*
|
||||
region 市名
|
||||
ref="SearchAddress"
|
||||
fnPick={this.fn.bind(this)}
|
||||
|
||||
// 打开
|
||||
this.refs.xxx.show()
|
||||
*/
|
||||
|
||||
class SearchStore extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
ani: new Animated.Value(clientH),
|
||||
storeList: [],
|
||||
keyword: ''
|
||||
};
|
||||
this.doSearch = debounce(this.doSearch, 1000)
|
||||
}
|
||||
componentDidUpdate () {
|
||||
if (this.scroll) {
|
||||
this.scroll.refresh();
|
||||
this.scroll.scrollTo(0, 0);
|
||||
} else {
|
||||
if (this.refs.scrollList) {
|
||||
this.scroll = new BScroll(this.refs.scrollList, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// 查询门店
|
||||
async getAPI (keyword) {
|
||||
try {
|
||||
let {stores} = await fetchJson(`/v2/store/GetStores?keyword=${this.state.keyword}&pageSize=10`);
|
||||
console.log(stores)
|
||||
if (stores) {
|
||||
this.setState({storeList: stores});
|
||||
} else {
|
||||
this.setState({storeList: []});
|
||||
}
|
||||
} catch (e) {
|
||||
this.setState({storeList: []});
|
||||
}
|
||||
}
|
||||
// 输入关键词
|
||||
async handleKeyword (e) {
|
||||
// let _this = this
|
||||
// debounce(async (e) => {
|
||||
// console.log(e.target.value)
|
||||
// await _this.setState({keyword: e.target.value});
|
||||
// await _this.getAPI(_this.state.keyword);
|
||||
// }, 1000)
|
||||
this.doSearch(e.target.value)
|
||||
}
|
||||
doSearch = async (value) => {
|
||||
await this.setState({keyword: value});
|
||||
await this.getAPI(this.state.keyword);
|
||||
}
|
||||
// show
|
||||
async show () {
|
||||
await this.setState({show: true, storeList: []});
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 300
|
||||
}).start();
|
||||
this.refs.scrollList.addEventListener('scroll', this.handleBlur.bind(this));
|
||||
// this.refs.keyword.focus();
|
||||
await this.getAPI(this.state.keyword);
|
||||
}
|
||||
hide () {
|
||||
this.setState({show: false, ani: new Animated.Value(clientH)});
|
||||
this.refs.scrollList.removeEventListener('scroll', this.handleBlur.bind(this));
|
||||
this.scroll = null;
|
||||
}
|
||||
// 滚动失去焦点
|
||||
handleBlur () {
|
||||
this.refs.keyword.blur();
|
||||
}
|
||||
// 选取地址
|
||||
fnClick (item) {
|
||||
// console.log(item);
|
||||
this.props.fnPick && this.props.fnPick(item);
|
||||
this.hide();
|
||||
}
|
||||
// 返回
|
||||
fnReturn () {
|
||||
console.log('返回');
|
||||
this.hide();
|
||||
}
|
||||
// 清除
|
||||
fnClear = () => {
|
||||
this.props.fnClear && this.props.fnClear()
|
||||
this.hide()
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={classNames("zy-ui-checklist search-address", {'pointerAll': this.state.show})}>
|
||||
{
|
||||
this.state.show && (
|
||||
<div className="zy-ui-checklist-mask" onClick={this.hide.bind(this)}>
|
||||
<Animated.div className="zy-ui-checklist-wrapper" style={{transform: [{translateY: this.state.ani}]}} onClick={e => e.stopPropagation()}>
|
||||
<div className="zy-ui-address-header store-pick">
|
||||
<div className="zy-ui-checklist-return" onClick={this.fnReturn.bind(this)}>返回</div>
|
||||
<div className="zy-ui-address-input">
|
||||
<input ref="keyword" type="text" onChange={this.handleKeyword.bind(this)} placeholder="请输入门店关键字"/>
|
||||
<ReactSVG className="svg" src={SVGAddress}></ReactSVG>
|
||||
</div>
|
||||
{
|
||||
this.props.fnClear && (
|
||||
<div className="zy-ui-checklist-clear" onClick={this.fnClear}>清除选择</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className="zy-ui-address-body" ref="scrollList">
|
||||
<div>
|
||||
{
|
||||
this.state.storeList.length > 0 && this.state.storeList.map(store => (
|
||||
<div className="address-item" key={store.id} onClick={this.fnClick.bind(this, store)}>
|
||||
<ReactSVG className="svg" src={SVGAddress}></ReactSVG>
|
||||
<div className="address-content">
|
||||
<div className="content1">{store.name}</div>
|
||||
<div className="content2">ID:{store.id} {store.cityName}-{store.districtName}</div>
|
||||
</div>
|
||||
<div className="pick-text">选择</div>
|
||||
</div>
|
||||
// <div>111</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SearchStore;
|
||||
140
src/components/layout/SearchUser.js
Normal file
140
src/components/layout/SearchUser.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import React, { Component } from 'react';
|
||||
import Animated from 'animated/lib/targets/react-dom';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import BScroll from 'better-scroll';
|
||||
import './main.scss';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import ReactSVG from 'react-svg'
|
||||
import SVGAddress from '@/assets/svg/icon-user.svg';
|
||||
// import SVGAddressList from '@/assets/svg/icon-addresslist.svg';
|
||||
|
||||
const clientH = document.documentElement.clientHeight;
|
||||
/*
|
||||
region 市名
|
||||
ref="SearchAddress"
|
||||
fnPick={this.fn.bind(this)}
|
||||
|
||||
// 打开
|
||||
this.refs.xxx.show()
|
||||
*/
|
||||
|
||||
class SearchUser extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
show: false,
|
||||
ani: new Animated.Value(clientH),
|
||||
userList: [],
|
||||
keyword: ''
|
||||
};
|
||||
}
|
||||
componentDidUpdate () {
|
||||
if (this.scroll) {
|
||||
this.scroll.refresh();
|
||||
this.scroll.scrollTo(0, 0);
|
||||
} else {
|
||||
if (this.refs.scrollList) {
|
||||
this.scroll = new BScroll(this.refs.scrollList, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// 查询门店
|
||||
async getAPI (keyword) {
|
||||
try {
|
||||
let {data} = await fetchJson(`/v2/user2/GetUsers?keyword=${keyword}&userType=14&offset=0&pageSize=20`);
|
||||
console.log('用户列表', data)
|
||||
if (data) {
|
||||
this.setState({userList: data});
|
||||
} else {
|
||||
this.setState({userList: []});
|
||||
}
|
||||
} catch (e) {
|
||||
this.setState({userList: []});
|
||||
}
|
||||
}
|
||||
// 输入关键词
|
||||
async handleKeyword (e) {
|
||||
await this.setState({keyword: e.target.value});
|
||||
await this.getAPI(this.state.keyword);
|
||||
}
|
||||
// show
|
||||
async show () {
|
||||
await this.setState({show: true, userList: []});
|
||||
Animated.timing(this.state.ani, {
|
||||
toValue: 0,
|
||||
duration: 300
|
||||
}).start();
|
||||
this.refs.scrollList.addEventListener('scroll', this.handleBlur.bind(this));
|
||||
// this.refs.keyword.focus();
|
||||
await this.getAPI(this.state.keyword);
|
||||
}
|
||||
hide () {
|
||||
this.setState({show: false, ani: new Animated.Value(clientH)});
|
||||
this.refs.scrollList.removeEventListener('scroll', this.handleBlur.bind(this));
|
||||
this.scroll = null;
|
||||
}
|
||||
// 滚动失去焦点
|
||||
handleBlur () {
|
||||
this.refs.keyword.blur();
|
||||
}
|
||||
// 选取地址
|
||||
fnClick (item) {
|
||||
// console.log(item);
|
||||
this.props.fnPick && this.props.fnPick(item);
|
||||
this.hide();
|
||||
}
|
||||
// 返回
|
||||
fnReturn () {
|
||||
console.log('返回');
|
||||
this.hide();
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={classNames("zy-ui-checklist search-address", {'pointerAll': this.state.show})}>
|
||||
{
|
||||
this.state.show && (
|
||||
<div className="zy-ui-checklist-mask" onClick={this.hide.bind(this)}>
|
||||
<Animated.div className="zy-ui-checklist-wrapper" style={{transform: [{translateY: this.state.ani}]}} onClick={e => e.stopPropagation()}>
|
||||
<div className="zy-ui-address-header">
|
||||
<div className="zy-ui-checklist-return" onClick={this.fnReturn.bind(this)}>返回</div>
|
||||
<div className="zy-ui-address-input">
|
||||
<input ref="keyword" type="text" onChange={this.handleKeyword.bind(this)} placeholder="请输入关键字进行检索"/>
|
||||
<ReactSVG className="svg" src={SVGAddress}></ReactSVG>
|
||||
</div>
|
||||
</div>
|
||||
<div className="zy-ui-address-body" ref="scrollList">
|
||||
<div>
|
||||
{
|
||||
this.state.userList.length > 0 && this.state.userList.map(user => (
|
||||
<div className="address-item" key={user.id} onClick={this.fnClick.bind(this, user)}>
|
||||
<ReactSVG className="svg" src={SVGAddress}></ReactSVG>
|
||||
<div className="address-content">
|
||||
<div className="content1">{user.name}</div>
|
||||
<div className="content2">tel:{user.mobile}</div>
|
||||
</div>
|
||||
<div className="pick-text">选择</div>
|
||||
</div>
|
||||
// <div>111</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Animated.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SearchUser;
|
||||
21
src/components/layout/Tabs.js
Normal file
21
src/components/layout/Tabs.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
class Tabs extends Component {
|
||||
render() {
|
||||
return (
|
||||
<ul className="zy-ui-tabs">
|
||||
{
|
||||
this.props.fields && this.props.fields.map(field => (
|
||||
<li className={classNames('zy-ui-tabs-item', {'zy-ui-tabs-item-active': this.props.current === field.index})} key={field.index} onClick={() => {
|
||||
this.props.fnClick(field.index)
|
||||
}}>{field.text}</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Tabs;
|
||||
436
src/components/layout/main.scss
Normal file
436
src/components/layout/main.scss
Normal file
@@ -0,0 +1,436 @@
|
||||
// 弹出窗口
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
.popup-page, .popup-page2 {
|
||||
.popup-wrapper {
|
||||
position: fixed;
|
||||
z-index: 2000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: white;
|
||||
}
|
||||
.popup-wrapper-main {
|
||||
bottom: 1rem;
|
||||
}
|
||||
|
||||
.popup-menu {
|
||||
height: 1rem;
|
||||
background: $blue;
|
||||
}
|
||||
.popup-content {
|
||||
// position: absolute;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
// top: 1rem;
|
||||
height: calc(100vh - 1rem);
|
||||
// overflow-y: auto;
|
||||
overflow: hidden;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
background: #fafafa;
|
||||
// touch-action: none;
|
||||
// pointer-events: none;
|
||||
}
|
||||
.popup-content-main {
|
||||
height: calc(100% - 1rem);
|
||||
}
|
||||
.popup-menu {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
// padding: 0 .2rem;
|
||||
}
|
||||
.menu-center {
|
||||
justify-content: center;
|
||||
}
|
||||
.popup-title {
|
||||
color: white;
|
||||
font-size: .32rem;
|
||||
padding: 0 .2rem;
|
||||
.svg {
|
||||
display: inline-block;
|
||||
margin-right: .1rem;
|
||||
vertical-align: -0.06rem;
|
||||
svg {
|
||||
fill: white;
|
||||
width: .34rem;
|
||||
height: .34rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-return, .btn-confirm {
|
||||
color: $gray;
|
||||
font-size: .28rem;
|
||||
// padding: .1rem .4rem;
|
||||
height: 100%;
|
||||
width: 1.6rem;
|
||||
// border: 1px solid white;
|
||||
border-radius: .1rem;
|
||||
display: flex;
|
||||
.icon {
|
||||
margin: auto 0;
|
||||
svg {
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-return {
|
||||
.icon {
|
||||
margin-left: .1rem;
|
||||
}
|
||||
}
|
||||
.btn-confirm {
|
||||
justify-content: flex-end;
|
||||
.icon {
|
||||
margin-right: .1rem;
|
||||
}
|
||||
.btn-confirm-text {
|
||||
margin: auto 0;
|
||||
margin-right: .2rem;
|
||||
color: white;
|
||||
font-size: .32rem;
|
||||
// text-decoration: underline;
|
||||
// font-weight: bold;
|
||||
background: $success;
|
||||
padding: .14rem .3rem;
|
||||
border-radius: .1rem;
|
||||
border: 1px solid white;
|
||||
// box-shadow: 0 0 .05rem rgba($gray, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-page2 {
|
||||
.popup-wrapper {
|
||||
position: static;
|
||||
}
|
||||
.popup-content-main {
|
||||
height: calc(100% - 2rem);
|
||||
}
|
||||
}
|
||||
|
||||
// 单选 多选
|
||||
.zy-ui-radio, .zy-ui-checkbox {
|
||||
display: flex;
|
||||
font-size: .28rem;
|
||||
// border-radius: .1rem;
|
||||
flex-flow: row wrap;
|
||||
.zy-ui-radio-btn, .zy-ui-checkbox-btn {
|
||||
background: $gray;
|
||||
color: white;
|
||||
padding: .18rem;
|
||||
transition: all .3s ease-in-out;
|
||||
// &:first-of-type {
|
||||
// border-top-left-radius: .1rem;
|
||||
// border-bottom-left-radius: .1rem;
|
||||
// }
|
||||
// &:last-of-type {
|
||||
// border-top-right-radius: .1rem;
|
||||
// border-bottom-right-radius: .1rem;
|
||||
// }
|
||||
}
|
||||
.zy-ui-radio-btn-active {
|
||||
background: $blue;
|
||||
}
|
||||
.zy-ui-checkbox-btn-active {
|
||||
background: $success;
|
||||
}
|
||||
.zy-ui-checkbox-check-true {
|
||||
display: inline-block;
|
||||
width: .4rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
&:before {
|
||||
content: "✔\fe0e";
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
.zy-ui-checkbox-check-false {
|
||||
display: inline-block;
|
||||
width: .4rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
&:before {
|
||||
content: "✘";
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkList 列表单选
|
||||
.zy-ui-checklist {
|
||||
.zy-ui-checklist-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(black, .4);
|
||||
z-index: 3000;
|
||||
}
|
||||
.zy-ui-checklist-wrapper {
|
||||
background: white;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
border-top-left-radius: .2rem;
|
||||
border-top-right-radius: .2rem;
|
||||
padding: .2rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.zy-ui-checklist-header {
|
||||
font-size: .32rem;
|
||||
height: .8rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid $blue;
|
||||
}
|
||||
.zy-ui-checklist-return {
|
||||
position: absolute;
|
||||
line-height: .8rem;
|
||||
// background: red;
|
||||
width: 1.5rem;
|
||||
color: $sliver;
|
||||
font-size: .3rem;
|
||||
z-index: 1;
|
||||
}
|
||||
.zy-ui-checklist-title {
|
||||
line-height: .8rem;
|
||||
text-align: center;
|
||||
color: $blue;
|
||||
}
|
||||
.zy-ui-checklist-body {
|
||||
font-size: .3rem;
|
||||
height: calc(100% - .8rem);
|
||||
overflow: hidden;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
& > div {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
.zy-ui-checklist-item {
|
||||
text-align: center;
|
||||
padding: .2rem;
|
||||
border-radius: .5rem;
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.zy-ui-checklist-item-active {
|
||||
background: $lightBlue;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
.zy-ui-address-header {
|
||||
font-size: .32rem;
|
||||
height: .8rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid $sliver;
|
||||
// width: 100%;
|
||||
.zy-ui-checklist-return {
|
||||
width: 1.2rem;
|
||||
// background: red;
|
||||
}
|
||||
.zy-ui-checklist-position {
|
||||
position: absolute;
|
||||
// background: red;
|
||||
width: 1rem;
|
||||
color: $sliver;
|
||||
font-size: .3rem;
|
||||
z-index: 1;
|
||||
top: .38rem;
|
||||
right: .2rem;
|
||||
text-align: center;
|
||||
.my-position {
|
||||
svg {
|
||||
fill: $sliver;
|
||||
width: .36rem;
|
||||
height: .36rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-ui-address-input {
|
||||
text-align: center;
|
||||
// background: green;
|
||||
margin-left: 1.2rem;
|
||||
height: 100%;
|
||||
// width: 5rem;
|
||||
position: relative;
|
||||
}
|
||||
input {
|
||||
font-size: .32rem;
|
||||
position: absolute;
|
||||
left: 2.24rem;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: .1rem .2rem;
|
||||
padding-left: .8rem;
|
||||
outline: none;
|
||||
border-radius: .1rem;
|
||||
border: 1px solid $sliver;
|
||||
width: 3.6rem;
|
||||
}
|
||||
.svg {
|
||||
position: absolute;
|
||||
left: .2rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
svg {
|
||||
fill: $sliver;
|
||||
width: .36rem;
|
||||
height: .36rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.store-pick {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.zy-ui-address-header {
|
||||
position: static;
|
||||
}
|
||||
.zy-ui-address-input {
|
||||
flex: 1;
|
||||
margin-left: 0;
|
||||
}
|
||||
.zy-ui-checklist-return {
|
||||
position: static;
|
||||
flex:none;
|
||||
}
|
||||
.zy-ui-checklist-clear {
|
||||
flex: none;
|
||||
line-height: .8rem;
|
||||
// background: red;
|
||||
width: 1.5rem;
|
||||
color: $sliver;
|
||||
font-size: .3rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.zy-ui-address-body {
|
||||
height: calc(100% - .8rem);
|
||||
overflow: hidden;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.address-item {
|
||||
font-size: .32rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid $gray;
|
||||
padding: .2rem;
|
||||
.svg {
|
||||
width: .6rem;
|
||||
flex-shrink: 0;
|
||||
svg {
|
||||
fill: $success;
|
||||
width: .4rem;
|
||||
height: .4rem;
|
||||
}
|
||||
}
|
||||
.address-content {
|
||||
flex: 1;
|
||||
.content1 {}
|
||||
.content2 {
|
||||
margin-top: .1rem;
|
||||
color: $sliver;
|
||||
font-size: .24rem;
|
||||
}
|
||||
}
|
||||
.pick-text {
|
||||
flex-shrink: 0;
|
||||
color: $blue;
|
||||
width: .8rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 地址列表
|
||||
.search-address {
|
||||
|
||||
}
|
||||
|
||||
// Tabs
|
||||
.zy-ui-tabs {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: .32rem;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
background: white;
|
||||
box-shadow: 0 0 .05rem $gray;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
.zy-ui-tabs-item {
|
||||
list-style: none;
|
||||
height: .8rem;
|
||||
line-height: .8rem;
|
||||
padding: 0 .2rem;
|
||||
box-sizing: border-box;
|
||||
color: $black;
|
||||
transition: all .3s;
|
||||
}
|
||||
.zy-ui-tabs-item-active {
|
||||
border-bottom: .04rem solid $blue;
|
||||
color: $blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
// 选择输入框
|
||||
.zy-ui-pick-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
.zy-ui-pick-btn {
|
||||
display: flex;
|
||||
color: $sliver;
|
||||
width: 2rem;
|
||||
flex-shrink: 0;
|
||||
.zy-ui-pick-icon {
|
||||
svg {
|
||||
width: .32rem;
|
||||
height: .32rem;
|
||||
fill: $sliver;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-ui-pick-cmpinput {
|
||||
color: $black;
|
||||
border: 1px solid $gray;
|
||||
padding: .1rem;
|
||||
border-radius: .1rem;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
.zy-ui-pick-confirmbtn {
|
||||
flex-shrink: 0;
|
||||
margin-left: .2rem;
|
||||
padding: .14rem .3rem;
|
||||
border-radius: .1rem;
|
||||
background: $primary;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.zy-ui-keywordsearch {
|
||||
border: 1px solid $gray;
|
||||
padding: .1rem .2rem;
|
||||
border-radius: .1rem;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
.placeholder {
|
||||
color: $sliver;
|
||||
// box-sizing: border-box;
|
||||
width: 100%;
|
||||
// white-space:nowrap;
|
||||
// overflow:hidden;
|
||||
// text-overflow:ellipsis;
|
||||
}
|
||||
.name {
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
525
src/components/pageCmp/CmpModifyBase.js
Normal file
525
src/components/pageCmp/CmpModifyBase.js
Normal file
@@ -0,0 +1,525 @@
|
||||
import React, { Component } from 'react';
|
||||
import './cmp-modify.scss';
|
||||
import {connect} from 'react-redux';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import Loading from '@/components/Loading';
|
||||
import {isNum, isEmpty, isTel, isTel2} from '@/utils/regExp';
|
||||
import {businessHours, dealOpenTime} from '@/utils/projectTools';
|
||||
import Dialog from '@/components/Dialog';
|
||||
import CheckList from '@/components/layout/CheckList';
|
||||
import {mapPlaces} from '@/utils/mapData';
|
||||
import ReactSVG from 'react-svg'
|
||||
import SVGGo from '@/assets/svg/icon-go.svg';
|
||||
import Toast from '@/components/Toast';
|
||||
import BScroll from 'better-scroll';
|
||||
import {formatDate} from '@/utils/tools'
|
||||
|
||||
// import PopupPage from '@/components/layout/PopupPage';
|
||||
import Input from './Input';
|
||||
import Radio from '@/components/layout/Radio';
|
||||
import SearchAddress from '@/components/layout/SearchAddress';
|
||||
|
||||
class CmpModifyBase extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
districtData: [],
|
||||
keyword: '',
|
||||
// printerType: null,
|
||||
printerInfo: [],
|
||||
printerVendorInfoArr: [],
|
||||
autoEnableAt: 0,
|
||||
autoTime: [
|
||||
{
|
||||
label: '将在明天自动营业',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: '将在后天自动营业',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
this.scroll = null;
|
||||
this.timeList = businessHours();
|
||||
this.uniArr = ['status', 'openTime1', 'closeTime1', 'openTime2', 'closeTime2', 'autoEnableAt'];
|
||||
this.showTestPrint = this.props.shop.printerVendorID !== 0;
|
||||
}
|
||||
async componentDidMount () {
|
||||
await this.setState(prev => {
|
||||
return {
|
||||
...prev,
|
||||
...this.props.shop
|
||||
};
|
||||
});
|
||||
// await this.getStore();
|
||||
console.log(this.state)
|
||||
await this.getDistrict();
|
||||
// 打印厂商
|
||||
let {printerVendorInfo} = this.props.system.cms;
|
||||
// [
|
||||
// {value: 0, label: '无'},
|
||||
// {value: 200, label: '飞鹅'},
|
||||
// {value: 201, label: '外卖管家'}
|
||||
// ]
|
||||
let printerVendorInfoArr = [
|
||||
{value: 0, label: '无'}
|
||||
];
|
||||
for (let attr in printerVendorInfo) {
|
||||
printerVendorInfoArr.push({
|
||||
value: parseInt(attr, 10),
|
||||
label: printerVendorInfo[attr][0]
|
||||
});
|
||||
}
|
||||
this.setState({printerVendorInfoArr});
|
||||
// 设置打印机信息
|
||||
this.setState({
|
||||
printerInfo: printerVendorInfo[this.state.printerVendorID] || []
|
||||
});
|
||||
this.scroll = new BScroll(this.refs.baseWrapper, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
// 获取区信息
|
||||
async getDistrict () {
|
||||
Loading.show();
|
||||
try {
|
||||
// 请求城市列表 level = 2
|
||||
let res = await fetchJson('/v2/cms/GetPlaces?parentCode=' + this.state.cityCode);
|
||||
console.log('区信息', mapPlaces(res));
|
||||
await this.setState({districtData: mapPlaces(res)});
|
||||
} catch (e) {} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 修改属性
|
||||
async handleModify (key, val) {
|
||||
console.log(key, val);
|
||||
if (this.uniArr.some(item => item.indexOf(key) !== -1)) {
|
||||
// 单独请求接口
|
||||
await this.apiTimeAndStatus(key, val);
|
||||
}
|
||||
if (key === 'autoEnableAt') {
|
||||
let autoEnableAt = val ? formatDate(+new Date() + 2 * 24 * 3600 * 1000, 'YYYY-MM-DD') : formatDate(+new Date() + 1 * 24 * 3600 * 1000, 'YYYY-MM-DD')
|
||||
this.setState({status: 0, autoEnableAt})
|
||||
} else {
|
||||
await this.setState({[key]: val});
|
||||
if (key === 'status' && val !== 0) {
|
||||
this.setState({autoEnableAt: null})
|
||||
}
|
||||
}
|
||||
// 网络打印机
|
||||
if (key === 'printerVendorID') {
|
||||
console.log('key == printerVendorID');
|
||||
// 清空sn和key
|
||||
this.setState({
|
||||
printerSN: '',
|
||||
printerKey: ''
|
||||
});
|
||||
this.showTestPrint = false // 切换打印机,隐藏测试打印按钮
|
||||
this.refs.printerSN && this.refs.printerSN.fnClear();
|
||||
this.refs.printerKey && this.refs.printerKey.fnClear();
|
||||
if (val === 0) {
|
||||
this.setState({
|
||||
printerInfo: [
|
||||
{value: 0, label: '无'}
|
||||
]
|
||||
});
|
||||
} else {
|
||||
let {printerVendorInfo} = this.props.system.cms;
|
||||
this.setState({
|
||||
printerInfo: printerVendorInfo[val]
|
||||
});
|
||||
}
|
||||
}
|
||||
if (key === 'cityCode') {
|
||||
await this.getDistrict();
|
||||
await this.setState({districtCode: this.state.districtData[0].code});
|
||||
}
|
||||
if (key === 'openTime1' && val === 0) this.setState({closeTime1: 0});
|
||||
if (key === 'openTime2' && val === 0) this.setState({closeTime2: 0});
|
||||
if (key === 'closeTime1' && val === 0) this.setState({openTime1: 0});
|
||||
if (key === 'closeTime2' && val === 0) this.setState({openTime2: 0});
|
||||
}
|
||||
// 单独请求接口
|
||||
async apiTimeAndStatus (key, val) {
|
||||
try {
|
||||
Loading.show();
|
||||
let json = {};
|
||||
if (this.uniArr.some(item => item.indexOf(key) !== -1)) {
|
||||
if (key === 'openTime1' && val === 0) json['closeTime1'] = 0
|
||||
if (key === 'openTime2' && val === 0) json['closeTime2'] = 0
|
||||
if (key === 'closeTime1' && val === 0) json['openTime1'] = 0
|
||||
if (key === 'closeTime2' && val === 0) json['openTime2'] = 0
|
||||
}
|
||||
if (key === 'autoEnableAt') {
|
||||
json.status = 0
|
||||
json[key] = val ? formatDate(+new Date() + 2 * 24 * 3600 * 1000, 'YYYY-MM-DD') : formatDate(+new Date() + 1 * 24 * 3600 * 1000, 'YYYY-MM-DD')
|
||||
} else {
|
||||
json[key] = val;
|
||||
}
|
||||
let form = new FormData();
|
||||
form.append('storeID', this.state.id);
|
||||
form.append('payload', JSON.stringify(json));
|
||||
let res = await fetchJson('/v2/store/UpdateStore', {
|
||||
method: 'PUT',
|
||||
body: form
|
||||
});
|
||||
console.log(res);
|
||||
Toast.show('修改成功');
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 点击开始时间
|
||||
fnOpenTime (type) {
|
||||
if (type === 1) {
|
||||
this.refs.openTime1.show();
|
||||
} else {
|
||||
this.refs.openTime2.show();
|
||||
}
|
||||
}
|
||||
// 点击结束时间
|
||||
fnCloseTime (type) {
|
||||
if (type === 1) {
|
||||
this.refs.closeTime1.show();
|
||||
} else {
|
||||
this.refs.closeTime2.show();
|
||||
}
|
||||
}
|
||||
// 点击打印机类型
|
||||
fnPrinterVendorID () {
|
||||
this.refs.printerVendorID.show();
|
||||
}
|
||||
// 处理打印机类型
|
||||
dealPrinterVendorID (type) {
|
||||
if (type === 0) {
|
||||
return '无';
|
||||
} else {
|
||||
let {printerVendorInfo} = this.props.system.cms;
|
||||
return printerVendorInfo[type][0];
|
||||
}
|
||||
}
|
||||
// 点击市选择
|
||||
async fnCityPick () {
|
||||
this.refs.cityCode.show();
|
||||
}
|
||||
// 点击区选择
|
||||
fnDistrictPick () {
|
||||
this.refs.districtCode.show();
|
||||
}
|
||||
// 接入地图
|
||||
showMap () {
|
||||
this.refs.SearchAddress.show();
|
||||
}
|
||||
// 选取地址
|
||||
addressPick (address) {
|
||||
console.log(address);
|
||||
this.setState({address: address.address || address.title, lat: address.location.lat, lng: address.location.lng});
|
||||
}
|
||||
// 删除按钮
|
||||
fnDelete () {
|
||||
Dialog.show('确认', `是否删除 ${this.state.name}`, {}, res => {
|
||||
// console.log(res);
|
||||
if (res) {
|
||||
// 开始删除
|
||||
}
|
||||
})
|
||||
}
|
||||
// 测试打印按钮
|
||||
async handleTestPrint () {
|
||||
console.log('测试打印');
|
||||
try {
|
||||
let form = new FormData();
|
||||
form.append('vendorOrderID', 'test');
|
||||
form.append('vendorID', this.state.id);
|
||||
let res = await fetchJson('/v2/order/PrintOrder', {
|
||||
method: 'PUT',
|
||||
body: form
|
||||
});
|
||||
console.log('测试打印', res);
|
||||
if (res.printerStatus === 2) {
|
||||
Toast.show('测试打印发送成功');
|
||||
} else {
|
||||
Toast.show('打印机状态错误');
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {}
|
||||
}
|
||||
// 确认前
|
||||
async fnSubmit () {
|
||||
console.log(this.state);
|
||||
// 存放错误消息
|
||||
let arr = [];
|
||||
if (!isNum(this.state.id)) arr.push('京西门店ID必须是纯数字');
|
||||
if (!isEmpty(this.state.name)) arr.push('店铺名称不能为空');
|
||||
if (!isTel(this.state.tel1)) arr.push('店长手机不合法');
|
||||
if (!this.state.address) arr.push('请输入门店详细地址');
|
||||
if (this.state.deliveryRangeType === 3 && !isNum(this.state.deliveryRange)) arr.push('配送半径不合法');
|
||||
if (this.state.printerVendorID !== 0 && !isEmpty(this.state.printerSN)) arr.push('请填写' + this.state.printerInfo[1])
|
||||
if ((this.state.printerVendorID !== 0 && this.state.printerVendorID !== 202) && !isEmpty(this.state.printerKey)) arr.push('请填写' + this.state.printerInfo[2])
|
||||
|
||||
if (arr.length > 0) {
|
||||
Dialog.show('错误', `<span class="error">${arr.join('<br />')}</span>`, {
|
||||
showCancel: false,
|
||||
confirmText: '好的'
|
||||
})
|
||||
return false;
|
||||
} else {
|
||||
// 开始修改门店
|
||||
try {
|
||||
Loading.show();
|
||||
let form = new FormData();
|
||||
let json = JSON.parse(JSON.stringify(this.state));
|
||||
json.id = Number(json.id);
|
||||
// 清除无用数据
|
||||
delete json.districtData;
|
||||
delete json.keyword;
|
||||
delete json.createdAt;
|
||||
delete json.updatedAt;
|
||||
delete json.lastOperator;
|
||||
delete json.deletedAt;
|
||||
delete json.openTime2;
|
||||
delete json.closeTime2;
|
||||
delete json.idCardFront;
|
||||
delete json.idCardBack;
|
||||
delete json.idCardHand;
|
||||
delete json.licence;
|
||||
delete json.licenceCode;
|
||||
delete json.StoreMaps;
|
||||
delete json.CourierMaps;
|
||||
delete json.getVendorStore;
|
||||
// 单独请求接口
|
||||
delete json.status;
|
||||
delete json.openTime1;
|
||||
delete json.closeTime1;
|
||||
delete json.openTime2;
|
||||
delete json.closeTime2;
|
||||
form.append('storeID', json.id);
|
||||
form.append('payload', JSON.stringify(json));
|
||||
let res = await fetchJson('/v2/store/UpdateStore', {
|
||||
method: 'PUT',
|
||||
body: form
|
||||
});
|
||||
console.log(res);
|
||||
Dialog.show('成功', `<span class="success">${json.name} 修改成功</span>`, {showCancel: false, confirmText: '知道了'});
|
||||
return true;
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
return false;
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 临时休息
|
||||
fnAutoOpen () {
|
||||
this.refs.pickAutoOpen.show()
|
||||
}
|
||||
render() {
|
||||
let cityData = this.props.system.cityLevel2.find(item => item.code === this.state.cityCode);
|
||||
// 城市名称
|
||||
let cityName = cityData ? cityData.name : '未知'
|
||||
let districtData = this.state.districtData.find(item => item.code === this.state.districtCode);
|
||||
// 区名称
|
||||
let districtName = districtData ? districtData.name : '未知'
|
||||
return (
|
||||
<div className="cmp-modify-base">
|
||||
<div className="modify-base-wrapper" ref="baseWrapper">
|
||||
{
|
||||
this.state.id && (
|
||||
<div>
|
||||
<div className="header-title">基本信息</div>
|
||||
{/* 京西门店ID */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">京西门店ID:</div>
|
||||
<div className="cell-text">{this.state.id}</div>
|
||||
</div>
|
||||
{/* 店铺名称 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">店铺名称:</div>
|
||||
<Input check={isEmpty} errText="店铺名称不能为空" fnBlur={this.handleModify.bind(this, 'name')} value={this.state.name} placeholder="请输入店铺名称"></Input>
|
||||
</div>
|
||||
{/* 店长手机 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">店长手机:</div>
|
||||
<Input check={isTel} errText="店长手机不合法" fnBlur={this.handleModify.bind(this, 'tel1')} value={this.state.tel1} placeholder="请输入店长手机号" type="number"></Input>
|
||||
</div>
|
||||
{/* tel2 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">tel2:</div>
|
||||
<Input check={isTel2} errText="tel2手机不合法" fnBlur={this.handleModify.bind(this, 'tel2')} value={this.state.tel2} placeholder="请输入tel2(选填)" type="number"></Input>
|
||||
</div>
|
||||
{/* 营业时间 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">营业时间段1:</div>
|
||||
<div className="cell-time1">
|
||||
<div className="time" onClick={this.fnOpenTime.bind(this, 1)}>{dealOpenTime(this.state.openTime1)}</div>
|
||||
<span>至</span>
|
||||
<div className="time" onClick={this.fnCloseTime.bind(this, 1)}>{dealOpenTime(this.state.closeTime1)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">营业时间段2:</div>
|
||||
<div className="cell-time1">
|
||||
<div className="time" onClick={this.fnOpenTime.bind(this, 2)}>{dealOpenTime(this.state.openTime2)}</div>
|
||||
<span>至</span>
|
||||
<div className="time" onClick={this.fnCloseTime.bind(this, 2)}>{dealOpenTime(this.state.closeTime2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 营业状态 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">营业状态:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 1, text: '营业'},
|
||||
// {value: 0, text: '临时休息'},
|
||||
{value: -1, text: '长期休息'},
|
||||
{value: -2, text: '禁用'}
|
||||
]} id={'status'} current={this.state.status} fnClick={this.handleModify.bind(this, 'status')}></Radio>
|
||||
</div>
|
||||
</div>
|
||||
{/* 临时休息 */}
|
||||
<div className="create-cell auto-open">
|
||||
<div className="cell-label">临时休息:</div>
|
||||
{
|
||||
this.state.autoEnableAt ? (
|
||||
<div className="auto-open-text">
|
||||
将在 {formatDate(this.state.autoEnableAt, 'YYYY-MM-DD')} 自动营业
|
||||
</div>
|
||||
) : (
|
||||
<div className="auto-open-button" onClick={this.fnAutoOpen.bind(this)}>
|
||||
选择自动营业时间
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
{/* 价格审核 */}
|
||||
{/* <div className="create-cell">
|
||||
<div className="cell-label">价格审核:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 0, text: '关闭'},
|
||||
{value: 1, text: '开启'}
|
||||
]} id={'changePriceType'} current={this.state.changePriceType} fnClick={this.handleModify.bind(this, 'changePriceType')}></Radio>
|
||||
</div>
|
||||
</div> */}
|
||||
{/* 禁用网络打印 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">禁用网络打印机:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 0, text: '否'},
|
||||
{value: 1, text: '是'}
|
||||
]} id={'printerDisabled'} current={this.state.printerDisabled} fnClick={this.handleModify.bind(this, 'printerDisabled')}></Radio>
|
||||
</div>
|
||||
</div>
|
||||
{/* 打印机类型 */}
|
||||
<div className="create-cell printer-cell">
|
||||
<div className="cell-label">打印机品牌:</div>
|
||||
<div className="printer" onClick={this.fnPrinterVendorID.bind(this)}>{this.dealPrinterVendorID(this.state.printerVendorID)}</div>
|
||||
{
|
||||
this.showTestPrint && (
|
||||
<div className="test-print" onClick={this.handleTestPrint.bind(this)}>测试打印</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
{/* 网络打印机SN */}
|
||||
{
|
||||
(this.state.printerVendorID !== 0 && this.state.printerVendorInfoArr.length > 0) && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">{this.state.printerInfo[1]}</div>
|
||||
<Input ref="printerSN" fnBlur={this.handleModify.bind(this, 'printerSN')} value={this.state.printerSN} placeholder={'请填写' + this.state.printerInfo[1]}></Input>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 网络打印机KEY */}
|
||||
{
|
||||
(this.state.printerVendorID !== 0 && this.state.printerInfo[2] !== '不填' && this.state.printerVendorInfoArr.length > 0) && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">{this.state.printerInfo[2]}</div>
|
||||
<Input ref="printerKey" fnBlur={this.handleModify.bind(this, 'printerKey')} value={this.state.printerKey} placeholder={'请填写' + this.state.printerInfo[2]}></Input>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className="header-title">地址及配送范围</div>
|
||||
{/* 所在城市 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">所在城市:</div>
|
||||
<div className="cell-city">
|
||||
<div className="area" onClick={this.fnCityPick.bind(this)}>{cityName}</div>
|
||||
<div className="area" onClick={this.fnDistrictPick.bind(this)}>{districtName}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 详细地址 */}
|
||||
<div className="create-cell" onClick={this.showMap.bind(this)}>
|
||||
<div className="cell-label">详细地址:</div>
|
||||
<div className="cell-value">{this.state.address || '请填写详细地址'}</div>
|
||||
<ReactSVG src={SVGGo} className="icon"></ReactSVG>
|
||||
</div>
|
||||
|
||||
{/* 配送范围 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">配送范围:</div>
|
||||
{
|
||||
this.state.deliveryRangeType === 3 ? (
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 3, text: '半径服务'}
|
||||
]} id={'changePriceType'} current={this.state.deliveryRangeType} fnClick={this.handleModify.bind(this, 'deliveryRangeType')}></Radio>
|
||||
<Input className="rangeInput" check={isNum} errText="半径不合法" fnBlur={this.handleModify.bind(this, 'deliveryRange')} value={this.state.deliveryRange} placeholder="请输入半径" type="number"></Input>
|
||||
<div className="suffix">米</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="cell-value">
|
||||
规划范围
|
||||
{/* <Radio fields={[
|
||||
{value: 2, text: '规划范围'}
|
||||
]} id={'changePriceType'} current={this.state.deliveryRangeType} fnClick={this.handleModify.bind(this, 'deliveryRangeType')}></Radio> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
{/* 配送类型 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">配送类型:</div>
|
||||
<div className="cell-text">{this.props.system.cms.storeDeliveryType && this.props.system.cms.storeDeliveryType[this.state.deliveryType]}</div>
|
||||
</div>
|
||||
<div className="btn-group">
|
||||
{/* <div className="delete-btn" onClick={this.fnDelete.bind(this)}>删除门店</div> */}
|
||||
<div className="modify-btn" onClick={this.fnSubmit.bind(this)}>修改信息</div>
|
||||
</div>
|
||||
{/* <div className="padding-bottom-1rem"></div> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
{/* 时间checkList */}
|
||||
<CheckList ref="openTime1" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.openTime1} title="开始时间" fnPick={this.handleModify.bind(this, 'openTime1')}></CheckList>
|
||||
<CheckList ref="closeTime1" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.closeTime1} title="结束时间" fnPick={this.handleModify.bind(this, 'closeTime1')}></CheckList>
|
||||
<CheckList ref="openTime2" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.openTime2} title="开始时间" fnPick={this.handleModify.bind(this, 'openTime2')}></CheckList>
|
||||
<CheckList ref="closeTime2" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.closeTime2} title="结束时间" fnPick={this.handleModify.bind(this, 'closeTime2')}></CheckList>
|
||||
<CheckList ref="printerVendorID" datas={this.state.printerVendorInfoArr} map={{value: 'value', label: 'label'}} current={this.state.printerVendorID} title="网络打印机品牌" fnPick={this.handleModify.bind(this, 'printerVendorID')}></CheckList>
|
||||
{/* 自动营业时间选择 */}
|
||||
<CheckList ref="pickAutoOpen" datas={this.state.autoTime} map={{value: 'value', label: 'label'}} current={this.state.autoEnableAt} title="选择自动营业时间" fnPick={this.handleModify.bind(this, 'autoEnableAt')}></CheckList>
|
||||
{/* 市、区选择 */}
|
||||
<CheckList ref="cityCode" datas={this.props.system.cityLevel2} map={{value: 'code', label: 'name'}} current={this.state.cityCode} title="选择市" fnPick={this.handleModify.bind(this, 'cityCode')}></CheckList>
|
||||
<CheckList ref="districtCode" datas={this.state.districtData} map={{value: 'code', label: 'name'}} current={this.state.districtCode} title="选择区" fnPick={this.handleModify.bind(this, 'districtCode')}></CheckList>
|
||||
{/* 详细地址 */}
|
||||
<SearchAddress ref="SearchAddress" region={cityData ? cityData.name : ''} fnPick={this.addressPick.bind(this)}></SearchAddress>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect((state, props) => Object.assign({}, props, state), {})(CmpModifyBase);
|
||||
324
src/components/pageCmp/CmpModifyGroup.js
Normal file
324
src/components/pageCmp/CmpModifyGroup.js
Normal file
@@ -0,0 +1,324 @@
|
||||
import React, { Component } from 'react';
|
||||
import './cmp-modify.scss';
|
||||
// import {isTel} from '@/utils/regExp';
|
||||
// import classNames from 'classnames';
|
||||
import ReactSVG from 'react-svg';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import BScroll from 'better-scroll';
|
||||
|
||||
// import SVGModify from '@/assets/svg/icon-modify.svg';
|
||||
import SVGDelete from '@/assets/svg/icon-delete.svg';
|
||||
// import SVGPublic from '@/assets/svg/icon-public.svg';
|
||||
// import SVGMini from '@/assets/svg/icon-mini.svg';
|
||||
import SVGNoGroup from '@/assets/svg/no-group.svg';
|
||||
|
||||
import Dialog from '@/components/Dialog';
|
||||
import Loading from '@/components/Loading';
|
||||
|
||||
import Promopt from '@/components/Promopt';
|
||||
// import Input from './Input';
|
||||
import Toast from '@/components/Toast';
|
||||
import SearchUser from '@/components/layout/SearchUser';
|
||||
|
||||
class CmpModifyGroup extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
tel: ''
|
||||
};
|
||||
this.scroll = null;
|
||||
}
|
||||
componentDidMount () {
|
||||
this.scroll = new BScroll(this.refs.groupWrapper, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
// 打开对话框
|
||||
// showPromopt (options) {
|
||||
// let text = '';
|
||||
// if (options.type === 'addGroup') text = '添加分组';
|
||||
// if (options.type === 'addMembers') text = '添加组员';
|
||||
// this.refs.promopt.show(text, async res => {
|
||||
// if (res) {
|
||||
// if (!isTel(this.state.tel)) {
|
||||
// Toast.show('请输入正确的11位手机号', 2);
|
||||
// } else {
|
||||
// // 开始执行
|
||||
// if (options.type === 'addGroup') {
|
||||
// // 添加分组
|
||||
// await this.reqBindGroup(this.state.tel, options.storeID);
|
||||
// } else if (options.type === 'addMembers') {
|
||||
// // 添加组员
|
||||
// await this.reqaddMembers(options.parentMobile, this.state.tel);
|
||||
// } else if (options.type === 'changeMobile') {
|
||||
// // 修改号码
|
||||
// await this.reqChangeMobile(options.curMobile, this.state.tel);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// 手机号变化
|
||||
// async handleModify (key, val) {
|
||||
// // this.setState
|
||||
// console.log(key, val);
|
||||
// await this.setState({[key]: val.trim()});
|
||||
// }
|
||||
// 绑定分组
|
||||
// async reqBindGroup (mobile, storeID) {
|
||||
// try {
|
||||
// Loading.show();
|
||||
// let form = new FormData();
|
||||
// form.append('mobile', mobile);
|
||||
// form.append('storeID', storeID);
|
||||
// await fetchJson('/v2/user/TmpBindMobile2Store', {
|
||||
// method: 'PUT',
|
||||
// body: form
|
||||
// });
|
||||
// Toast.show('添加分组成功');
|
||||
// this.props.update && this.props.update();
|
||||
// } catch (e) {
|
||||
// Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
// } finally {
|
||||
// Loading.hide();
|
||||
// }
|
||||
// }
|
||||
// // 添加组员
|
||||
// async reqaddMembers (parentMobile, mobile) {
|
||||
// try {
|
||||
// Loading.show();
|
||||
// let form = new FormData();
|
||||
// form.append('mobile', mobile);
|
||||
// form.append('parentMobile', parentMobile);
|
||||
// await fetchJson('/v2/user/TmpAddMobile2Mobile', {
|
||||
// method: 'PUT',
|
||||
// body: form
|
||||
// });
|
||||
// Toast.show('添加组员成功');
|
||||
// this.props.update && this.props.update();
|
||||
// } catch (e) {
|
||||
// Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
// } finally {
|
||||
// Loading.hide();
|
||||
// }
|
||||
// }
|
||||
// // 修改号码
|
||||
// async reqChangeMobile (curMobile, expectedMobile) {
|
||||
// try {
|
||||
// Loading.show();
|
||||
// let form = new FormData();
|
||||
// form.append('curMobile', curMobile);
|
||||
// form.append('expectedMobile', expectedMobile);
|
||||
// await fetchJson('/v2/user/TmpChangeMobile', {
|
||||
// method: 'PUT',
|
||||
// body: form
|
||||
// });
|
||||
// Toast.show('修改号码成功');
|
||||
// this.props.update && this.props.update();
|
||||
// } catch (e) {
|
||||
// Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
// } finally {
|
||||
// Loading.hide();
|
||||
// }
|
||||
// }
|
||||
// 添加组员
|
||||
addUser = () => {
|
||||
this.refs.searchUser.show();
|
||||
}
|
||||
// 解绑操作
|
||||
async fnUnBind (user) {
|
||||
console.log(user);
|
||||
Dialog.show('警告', `<span class="error">是否删除 ${user.name}</span>`, {}, async res => {
|
||||
if (res) {
|
||||
try {
|
||||
console.log(this.props.storeID);
|
||||
// let form = new FormData();
|
||||
// form.append('mobile', tel);
|
||||
// Loading.show();
|
||||
// await fetchJson('/v2/user/TmpUnbindMobile', {
|
||||
// method: 'PUT',
|
||||
// body: form
|
||||
// });
|
||||
await fetchJson(`/v2/user2/DeleteUsers4Role?roleName=StoreBoss&storeID=${this.props.storeID}&userIDs=${JSON.stringify([user.userID])}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
Toast.show('删除成功');
|
||||
this.props.update && this.props.update();
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// 选择用户
|
||||
handlePick = async (user) => {
|
||||
console.log('选择的用户', user);
|
||||
try {
|
||||
Loading.show();
|
||||
let form = new FormData();
|
||||
form.append('roleName', 'StoreBoss');
|
||||
form.append('storeID', this.props.storeID);
|
||||
form.append('userIDs', JSON.stringify([user.userID]));
|
||||
await fetchJson('/v2/user2/AddUsers4Role', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
})
|
||||
Toast.show('添加成功');
|
||||
this.props.update && this.props.update();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 添加分组
|
||||
// bindGroup () {
|
||||
// // console.log(this.props.storeID);
|
||||
// this.showPromopt({
|
||||
// type: 'addGroup',
|
||||
// storeID: this.props.storeID
|
||||
// });
|
||||
// }
|
||||
// 添加组员
|
||||
// bindMembers (parentMobile) {
|
||||
// this.showPromopt({
|
||||
// type: 'addMembers',
|
||||
// parentMobile
|
||||
// });
|
||||
// }
|
||||
// 修改号码
|
||||
// modifyTel (curTel) {
|
||||
// console.log(curTel);
|
||||
// this.showPromopt({
|
||||
// type: 'changeMobile',
|
||||
// curMobile: curTel
|
||||
// });
|
||||
// }
|
||||
// 查询用户
|
||||
async getOneUser (mobile) {
|
||||
try {
|
||||
let {totalCount, data} = await fetchJson(`/v2/user2/GetUsers?userType=0&keyword=${mobile}`)
|
||||
return totalCount ? data[0] : null
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
// 注册
|
||||
async handleRegister (mobile) {
|
||||
try {
|
||||
let res = fetchJson(`/v2/user2/RegisterUser`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: `payload=${JSON.stringify({
|
||||
userID2: mobile,
|
||||
mobile,
|
||||
name: mobile
|
||||
})}`
|
||||
})
|
||||
return res
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
// 注册形式添加用户
|
||||
registerUser = () => {
|
||||
this.refs.promopt.show('请输入手机号', async res => {
|
||||
if (res) {
|
||||
const mobile = this.refs.telInput.value.trim()
|
||||
if (/^\d{11}$/.test(mobile)) {
|
||||
console.log(mobile)
|
||||
try {
|
||||
Loading.show()
|
||||
let user = await this.getOneUser(mobile)
|
||||
if (user) {
|
||||
// 用户存在,直接绑定
|
||||
console.log(user)
|
||||
await this.handlePick(user)
|
||||
} else {
|
||||
// 用户不存在,注册
|
||||
await this.handleRegister(mobile)
|
||||
let newUser = await this.getOneUser(mobile)
|
||||
await this.handlePick(newUser)
|
||||
}
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide()
|
||||
}
|
||||
} else {
|
||||
Toast.show('手机格式错误')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="cmp-modify-group">
|
||||
{/* 添加分组按钮 */}
|
||||
<div className="btn-group">
|
||||
<div className="btn-addGroup" onClick={this.addUser}>添加用户</div>
|
||||
<div className="btn-reg" onClick={this.registerUser}>注册用户</div>
|
||||
</div>
|
||||
{/* 分组显示 */}
|
||||
<div className="card-wrapper" ref="groupWrapper">
|
||||
<div>
|
||||
{
|
||||
this.props.users.length > 0 && this.props.users.map(user => (
|
||||
<div className="card" key={user.id}>
|
||||
<div className="card-group">
|
||||
<div className="card-left">
|
||||
{/* 昵称 */}
|
||||
<div className="nick-name"><b>{user.name || '无昵称'}</b></div>
|
||||
{/* 手机号 */}
|
||||
<div className="tel"><b>tel:{user.mobile}</b></div>
|
||||
{/* 绑定标识 */}
|
||||
{/* <div className="bind-id">
|
||||
<ReactSVG className={classNames('no-bind', {'is-bind': user.openID})} src={SVGPublic}></ReactSVG>
|
||||
<ReactSVG className={classNames('no-bind', {'is-bind': user.openIDMini})} src={SVGMini}></ReactSVG>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="card-right">
|
||||
{/* 操作 */}
|
||||
<div className="btn-delete" onClick={this.fnUnBind.bind(this, user)}>
|
||||
<ReactSVG className="svg" src={SVGDelete}></ReactSVG>
|
||||
</div>
|
||||
{/* <div className="btn-editor" onClick={this.modifyTel.bind(this, user.tel)}>
|
||||
<ReactSVG className="svg" src={SVGModify}></ReactSVG>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{/* 没有分组 */}
|
||||
</div>
|
||||
{
|
||||
this.props.users.length === 0 && (
|
||||
<div className="no-thing">
|
||||
<ReactSVG src={SVGNoGroup} className="no-store"/>
|
||||
<div className="text">该门店还没有分组</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<SearchUser ref="searchUser" fnPick={this.handlePick}></SearchUser>
|
||||
<Promopt ref="promopt">
|
||||
<input ref="telInput" className="tel-input" type="text"/>
|
||||
</Promopt>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CmpModifyGroup;
|
||||
90
src/components/pageCmp/CmpModifyMaps.js
Normal file
90
src/components/pageCmp/CmpModifyMaps.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import React, { Component } from 'react';
|
||||
import './cmp-modify.scss';
|
||||
// import fetchJson from '@/utils/fetch';
|
||||
// import Loading from '@/components/Loading';
|
||||
// import Dialog from '@/components/Dialog';
|
||||
|
||||
import VendorCell from './VendorCell';
|
||||
|
||||
class CmpModifyMaps extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
// StoreMaps: '',
|
||||
// CourierMaps: ''
|
||||
};
|
||||
}
|
||||
async componentDidMount () {
|
||||
await this.setState({...this.props.shop});
|
||||
console.log(this.state);
|
||||
// await this.getVendorMaps();
|
||||
}
|
||||
componentWillReceiveProps (newProps) {
|
||||
console.log('new Props', newProps);
|
||||
this.setState({...newProps.shop});
|
||||
}
|
||||
// 获取平台门店绑定情况
|
||||
// async getVendorMaps () {
|
||||
// try {
|
||||
// Loading.show();
|
||||
// let res = await fetchJson('/v2/store/GetStoreVendorMaps?storeID=' + this.props.shop.id);
|
||||
// console.log('平台门店绑定情况', res);
|
||||
// } catch (e) {
|
||||
// Dialog.show('错误', e, {showCancel: false});
|
||||
// } finally {
|
||||
// Loading.hide();
|
||||
// }
|
||||
// }
|
||||
render() {
|
||||
return (
|
||||
<div className="cmp-modify-maps">
|
||||
{
|
||||
this.state.id && (
|
||||
<div>
|
||||
<div className="header-title">平台门店绑定情况</div>
|
||||
{/* 京东 */}
|
||||
<VendorCell
|
||||
shop={this.state}
|
||||
plant={{name: 'StoreMaps', id: 0}}
|
||||
update={this.props.update}
|
||||
></VendorCell>
|
||||
{/* 美团 */}
|
||||
<VendorCell
|
||||
shop={this.state}
|
||||
plant={{name: 'StoreMaps', id: 1}}
|
||||
update={this.props.update}
|
||||
></VendorCell>
|
||||
{/* 饿百 */}
|
||||
<VendorCell
|
||||
shop={this.state}
|
||||
plant={{name: 'StoreMaps', id: 3}}
|
||||
update={this.props.update}
|
||||
></VendorCell>
|
||||
{/* 微盟 */}
|
||||
{/* <VendorCell
|
||||
shop={this.state}
|
||||
plant={{name: 'StoreMaps', id: 11}}
|
||||
update={this.props.update}
|
||||
></VendorCell> */}
|
||||
<div className="header-title">专送门店绑定情况</div>
|
||||
{/* 达达 */}
|
||||
<VendorCell
|
||||
shop={this.state}
|
||||
plant={{name: 'CourierMaps', id: 101}}
|
||||
update={this.props.update}
|
||||
></VendorCell>
|
||||
{/* 美团 */}
|
||||
<VendorCell
|
||||
shop={this.state}
|
||||
plant={{name: 'CourierMaps', id: 102}}
|
||||
update={this.props.update}
|
||||
></VendorCell>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CmpModifyMaps;
|
||||
530
src/components/pageCmp/CreateStore.js
Normal file
530
src/components/pageCmp/CreateStore.js
Normal file
@@ -0,0 +1,530 @@
|
||||
import React, { Component } from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import Loading from '@/components/Loading';
|
||||
import './create-store.scss';
|
||||
import {isNum, isEmpty, isTel, isTel2} from '@/utils/regExp';
|
||||
import {dealOpenTime, businessHours} from '@/utils/projectTools';
|
||||
import Dialog from '@/components/Dialog';
|
||||
import CheckList from '@/components/layout/CheckList';
|
||||
import {mapPlaces} from '@/utils/mapData';
|
||||
import ReactSVG from 'react-svg'
|
||||
import SVGGo from '@/assets/svg/icon-go.svg';
|
||||
import classNames from 'classnames';
|
||||
import BScroll from 'better-scroll';
|
||||
|
||||
import PopupPage from '@/components/layout/PopupPage';
|
||||
import Input from './Input';
|
||||
import Radio from '@/components/layout/Radio';
|
||||
import SearchAddress from '@/components/layout/SearchAddress';
|
||||
import PickInput from '@/components/layout/PickInput';
|
||||
|
||||
class CreateStore extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
id: 0,
|
||||
name: '',
|
||||
tel1: '',
|
||||
tel2: '',
|
||||
openTime1: 800,
|
||||
closeTime1: 1900,
|
||||
openTime2: 0,
|
||||
closeTime2: 0,
|
||||
status: -1,
|
||||
changePriceType: 0,
|
||||
cityCode: 510100,
|
||||
districtCode: null,
|
||||
address: '',
|
||||
deliveryRangeType: 3,
|
||||
deliveryRange: '3000',
|
||||
lng: '',
|
||||
lat: '',
|
||||
brandID:9,//品牌默认无 9
|
||||
payPercentage:20,//结算比例
|
||||
// 区数据
|
||||
districtData: [],
|
||||
keyword: '',
|
||||
// 获取平台数据
|
||||
vendorID: `0,${this.props.system.vendorOrgCode[0][0]}`,
|
||||
vendorStoreID: '',
|
||||
printerVendorID: 0,
|
||||
printerSN: '',
|
||||
printerKey: '',
|
||||
printerDisabled: 0,
|
||||
printerInfo: [],
|
||||
printerVendorInfoArr: []
|
||||
}
|
||||
this.scroll = null;
|
||||
this.timeList = businessHours();
|
||||
}
|
||||
async componentDidMount () {
|
||||
await this.getDistrict();
|
||||
// 打印厂商
|
||||
let {printerVendorInfo} = this.props.system.cms;
|
||||
console.log('printerVendorInfo', printerVendorInfo);
|
||||
// [
|
||||
// {value: 0, label: '无'},
|
||||
// {value: 200, label: '飞鹅'},
|
||||
// {value: 201, label: '外卖管家'}
|
||||
// ]
|
||||
let printerVendorInfoArr = [
|
||||
{value: 0, label: '无'}
|
||||
];
|
||||
for (let attr in printerVendorInfo) {
|
||||
printerVendorInfoArr.push({
|
||||
value: parseInt(attr, 10),
|
||||
label: printerVendorInfo[attr][0]
|
||||
});
|
||||
}
|
||||
this.setState({printerVendorInfoArr});
|
||||
}
|
||||
componentDidUpdate () {
|
||||
if (this.scroll) {
|
||||
this.scroll.refresh();
|
||||
} else {
|
||||
if (this.refs.createStoreWrapper) {
|
||||
this.scroll = new BScroll(this.refs.createStoreWrapper, {
|
||||
click: true,
|
||||
stopPropagation: true,
|
||||
bounce: {
|
||||
top: false,
|
||||
bottom: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// 请求次级数据
|
||||
async getDistrict () {
|
||||
Loading.show();
|
||||
try {
|
||||
// 请求城市列表 level = 2
|
||||
let res = await fetchJson('/v2/cms/GetPlaces?parentCode=' + this.state.cityCode);
|
||||
console.log('区信息', mapPlaces(res));
|
||||
await this.setState({districtData: mapPlaces(res)});
|
||||
await this.setState({districtCode: this.state.districtData[0].code});
|
||||
} catch (e) {} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// async getBrandList () {
|
||||
// Loading.show();
|
||||
// try {
|
||||
// // 请求城市列表 level = 2
|
||||
// let res = await fetchJson('/v2/store/GetBrands');
|
||||
// console.log('品牌', res);
|
||||
// } catch (e) {} finally {
|
||||
// Loading.hide();
|
||||
// }
|
||||
// }
|
||||
// 修改属性
|
||||
async handleModify (key, val) {
|
||||
console.log(key, val);
|
||||
console.log('this.state.printerInfo', this.state.printerInfo);
|
||||
await this.setState({[key]: val});
|
||||
if (key === 'printerVendorID') {
|
||||
this.setState({
|
||||
printerSN: '',
|
||||
printerKey: ''
|
||||
});
|
||||
this.refs.printerSN && this.refs.printerSN.fnClear();
|
||||
this.refs.printerKey && this.refs.printerKey.fnClear();
|
||||
if (val === 0) {
|
||||
this.setState({
|
||||
printerInfo: [
|
||||
{value: 0, label: '无'}
|
||||
]
|
||||
});
|
||||
} else {
|
||||
let {printerVendorInfo} = this.props.system.cms;
|
||||
this.setState({
|
||||
printerInfo: printerVendorInfo[val]
|
||||
});
|
||||
}
|
||||
}
|
||||
if (key === 'cityCode') {
|
||||
await this.getDistrict();
|
||||
}
|
||||
if (key === 'openTime1' && val === 0) this.setState({closeTime1: 0});
|
||||
if (key === 'openTime2' && val === 0) this.setState({closeTime2: 0});
|
||||
if (key === 'closeTime1' && val === 0) this.setState({openTime1: 0});
|
||||
if (key === 'closeTime2' && val === 0) this.setState({openTime2: 0});
|
||||
}
|
||||
// 点击开始时间
|
||||
fnOpenTime (type) {
|
||||
if (type === 1) {
|
||||
this.refs.openTime1.show();
|
||||
} else {
|
||||
this.refs.openTime2.show();
|
||||
}
|
||||
}
|
||||
fnBrandChoose(){
|
||||
this.refs.openTime2.show();
|
||||
}
|
||||
// 点击结束时间
|
||||
fnCloseTime (type) {
|
||||
if (type === 1) {
|
||||
this.refs.closeTime1.show();
|
||||
} else {
|
||||
this.refs.closeTime2.show();
|
||||
}
|
||||
}
|
||||
// 点击打印机类型
|
||||
fnPrinterVendorID () {
|
||||
this.refs.printerVendorID.show();
|
||||
}
|
||||
// 处理打印机类型
|
||||
dealPrinterVendorID (type) {
|
||||
// console.log(type);
|
||||
if (type === 0) {
|
||||
return '无';
|
||||
} else {
|
||||
let {printerVendorInfo} = this.props.system.cms;
|
||||
return printerVendorInfo[type][0];
|
||||
}
|
||||
}
|
||||
// 点击市选择
|
||||
async fnCityPick () {
|
||||
this.refs.cityCode.show();
|
||||
}
|
||||
// 点击区选择
|
||||
fnDistrictPick () {
|
||||
this.refs.districtCode.show();
|
||||
}
|
||||
// 接入地图
|
||||
showMap () {
|
||||
this.refs.SearchAddress.show();
|
||||
}
|
||||
// 选取地址
|
||||
addressPick (address) {
|
||||
console.log(address);
|
||||
this.setState({address: address.address || address.title, lat: address.location.lat, lng: address.location.lng});
|
||||
}
|
||||
// 点击半径
|
||||
rClick () {
|
||||
// console.log('点击半径', this.refs.PopupPage.toBottom())
|
||||
}
|
||||
// 校验
|
||||
fnCheckData () {
|
||||
let arr = [];
|
||||
if (!isNum(this.state.id)) arr.push('京西门店ID必须是纯数字');
|
||||
if (!isEmpty(this.state.name)) arr.push('店铺名称不能为空');
|
||||
if (!isTel(this.state.tel1)) arr.push('店长手机不合法');
|
||||
if (!this.state.address) arr.push('请输入门店详细地址');
|
||||
if (this.state.deliveryRangeType === 3 && !isNum(this.state.deliveryRange)) arr.push('配送半径不合法');
|
||||
if (this.state.printerVendorID !== 0 && !isEmpty(this.state.printerSN)) arr.push('请填写' + this.state.printerInfo[1])
|
||||
if ((this.state.printerVendorID !== 0 && this.state.printerVendorID !== 202) && !isEmpty(this.state.printerKey)) arr.push('请填写' + this.state.printerInfo[2])
|
||||
if (arr.length > 0) {
|
||||
Dialog.show('错误', `<span class="error">${arr.join('<br />')}</span>`, {
|
||||
showCancel: false,
|
||||
confirmText: '好的'
|
||||
})
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 确认前
|
||||
async prevConfirm () {
|
||||
console.log(this.state);
|
||||
if (this.fnCheckData()) {
|
||||
// 开始创建门店
|
||||
if (Number(this.state.id) !== 0) {
|
||||
Dialog.show('注意', `<span class="warning">京西门店ID正常都应该自动生成(京西门店ID为0时),您确认必须要设置成${this.state.id}?</span>`, {}, async (res) => {
|
||||
if (res) {
|
||||
let res = await this.apiCreateStore();
|
||||
return res;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let res = await this.apiCreateStore();
|
||||
return res;
|
||||
}
|
||||
} else {}
|
||||
}
|
||||
// 创建门店接口
|
||||
async apiCreateStore () {
|
||||
try {
|
||||
Loading.show();
|
||||
let form = new FormData();
|
||||
let json = JSON.parse(JSON.stringify(this.state));
|
||||
json.id = Number(json.id);
|
||||
delete json.districtData;
|
||||
delete json.keyword;
|
||||
form.append('payload', JSON.stringify(json));
|
||||
let res = await fetchJson('/v2/store/CreateStore', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
console.log(res);
|
||||
Dialog.show('成功', `${json.name} 创建成功`, {showCancel: false, confirmText: '知道了'});
|
||||
return true;
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
return false;
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// vendorID 修改
|
||||
handleVendorID = val => {
|
||||
console.log(val)
|
||||
this.setState({vendorID: val});
|
||||
}
|
||||
// vendorStoreID 修改
|
||||
handleVendorStoreID = val => {
|
||||
this.setState({vendorStoreID: val});
|
||||
}
|
||||
// 获取远端门店数据
|
||||
handleGetVendorStore = async () => {
|
||||
console.log(this.state.vendorID, this.state.vendorStoreID);
|
||||
let store = await this.getVendorStore();
|
||||
console.log(store);
|
||||
if (!store) return false;
|
||||
await this.setState({
|
||||
// id: store.id,
|
||||
name: store.name,
|
||||
tel1: store.tel1,
|
||||
tel2: store.tel2,
|
||||
openTime1: store.openTime1,
|
||||
closeTime1: store.closeTime1,
|
||||
status: store.status,
|
||||
changePriceType: store.changePriceType,
|
||||
cityCode: store.cityCode,
|
||||
districtCode: store.districtCode,
|
||||
address: store.address,
|
||||
// deliveryRangeType: 3,
|
||||
// deliveryRange: store.deliveryRangeType === 3,
|
||||
lng: store.lng,
|
||||
lat: store.lat,
|
||||
});
|
||||
// 单独处理配送范围
|
||||
if (store.deliveryRangeType === 3) this.setState({deliveryRange: store.deliveryRange});
|
||||
console.log(this.state)
|
||||
this.refs.name.checkData();
|
||||
this.refs.deliveryRange.checkData();
|
||||
this.refs.tel1.checkData();
|
||||
this.refs.tel2.checkData();
|
||||
}
|
||||
// 获取远端门店信息
|
||||
async getVendorStore () {
|
||||
try {
|
||||
Loading.show();
|
||||
let res = await fetchJson(`/v2/store/GetVendorStore?vendorStoreID=${this.state.vendorStoreID}&vendorID=${this.state.vendorID.split(',')[0]}&vendorOrgCode=${this.state.vendorID.split(',')[1]}`);
|
||||
// console.log(res);
|
||||
// 重新拉取区信息
|
||||
let district = await fetchJson('/v2/cms/GetPlaces?parentCode=' + res.cityCode);
|
||||
console.log('区信息', mapPlaces(district));
|
||||
await this.setState({districtData: mapPlaces(district)});
|
||||
// await this.setState({districtCode: this.state.districtData[0].code});
|
||||
return res;
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {
|
||||
showCancel: false,
|
||||
confirmText: '好的'
|
||||
});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
dealVendorOrgCode = () => {
|
||||
let vendorName = this.props.system.cms.vendorName || {};
|
||||
const {vendorOrgCode} = this.props.system
|
||||
console.log(vendorOrgCode)
|
||||
let arr = []
|
||||
for (let key in vendorOrgCode) {
|
||||
(vendorOrgCode[key] || []).forEach(item => {
|
||||
arr.push({
|
||||
id: `${key},${item}`,
|
||||
name: vendorName[key].substring(0, 1) + item
|
||||
})
|
||||
})
|
||||
}
|
||||
return arr
|
||||
// [
|
||||
// {id: 0, name: vendorName['0']},
|
||||
// {id: 1, name: vendorName['1']},
|
||||
// {id: 3, name: vendorName['3']}
|
||||
// ]
|
||||
}
|
||||
render () {
|
||||
let cityData = this.props.system.cityLevel2.find(item => item.code === this.state.cityCode);
|
||||
// 城市名称
|
||||
let cityName = cityData ? cityData.name : '未知'
|
||||
let districtData = this.state.districtData.find(item => item.code === this.state.districtCode);
|
||||
// 区名称
|
||||
let districtName = districtData ? districtData.name : '未知';
|
||||
return (
|
||||
<div className={classNames("create-store")}>
|
||||
<PopupPage
|
||||
className="create-store"
|
||||
ref="PopupPage"
|
||||
title="创建门店"
|
||||
fnReturn={this.props.fnReturn}
|
||||
fnPrevConfirm={this.prevConfirm.bind(this)}
|
||||
fnConfirm={this.props.fnConfirm}
|
||||
>
|
||||
<div className="create-store-wrapper" ref="createStoreWrapper">
|
||||
<div>
|
||||
{/* 从平台拉取数据 */}
|
||||
<div className="header-title">从平台获取数据</div>
|
||||
<div className="create-cell">
|
||||
<PickInput
|
||||
title="选择平台"
|
||||
placeholder="请输入平台门店ID"
|
||||
datas={this.dealVendorOrgCode()}
|
||||
map={{value: 'id', label: 'name'}}
|
||||
current={this.state.vendorID}
|
||||
fnPick={this.handleVendorID}
|
||||
fnChange={this.handleVendorStoreID}
|
||||
fnConfirm={this.handleGetVendorStore}
|
||||
type="number"
|
||||
></PickInput>
|
||||
</div>
|
||||
<div className="header-title">基本信息</div>
|
||||
{/* 京西门店ID */}
|
||||
<div className="create-cell has-suffix">
|
||||
<div className="cell-label">京西门店ID:</div>
|
||||
<Input check={isNum} errText="京西门店ID必须是纯数字" fnBlur={this.handleModify.bind(this, 'id')} value={this.state.id} placeholder="0 自动生成" type="number"></Input>
|
||||
<div className="suffix2">0表示自动生成缺省ID, 特殊情况可手动设置</div>
|
||||
</div>
|
||||
{/* 店铺名称 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">店铺名称:</div>
|
||||
<Input ref="name" check={isEmpty} errText="店铺名称不能为空" fnBlur={this.handleModify.bind(this, 'name')} value={this.state.name} placeholder="请输入店铺名称"></Input>
|
||||
</div>
|
||||
{/* 店长手机 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">店长手机:</div>
|
||||
<Input ref="tel1" check={isTel} errText="店长手机不合法" fnBlur={this.handleModify.bind(this, 'tel1')} value={this.state.tel1} placeholder="请输入店长手机号" type="number"></Input>
|
||||
</div>
|
||||
{/* tel2 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">tel2:</div>
|
||||
<Input ref="tel2" check={isTel2} errText="tel2手机不合法" fnBlur={this.handleModify.bind(this, 'tel2')} value={this.state.tel2} placeholder="请输入tel2(选填)" type="number"></Input>
|
||||
</div>
|
||||
{/* 营业时间 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">营业时间段1:</div>
|
||||
<div className="cell-time1">
|
||||
<div className="time" onClick={this.fnOpenTime.bind(this, 1)}>{dealOpenTime(this.state.openTime1)}</div>
|
||||
<span>至</span>
|
||||
<div className="time" onClick={this.fnCloseTime.bind(this, 1)}>{dealOpenTime(this.state.closeTime1)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">营业时间段2:</div>
|
||||
<div className="cell-time1">
|
||||
<div className="time" onClick={this.fnOpenTime.bind(this, 2)}>{dealOpenTime(this.state.openTime2)}</div>
|
||||
<span>至</span>
|
||||
<div className="time" onClick={this.fnCloseTime.bind(this, 2)}>{dealOpenTime(this.state.closeTime2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 营业状态 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">营业状态:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 1, text: '营业'},
|
||||
{value: -1, text: '长期休息'},
|
||||
{value: -2, text: '禁用'}
|
||||
]} id={'status'} current={this.state.status} fnClick={this.handleModify.bind(this, 'status')}></Radio>
|
||||
</div>
|
||||
</div>
|
||||
{/* 价格审核 */}
|
||||
{/* <div className="create-cell">
|
||||
<div className="cell-label">价格审核:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 0, text: '关闭'},
|
||||
{value: 1, text: '开启'}
|
||||
]} id={'changePriceType'} current={this.state.changePriceType} fnClick={this.handleModify.bind(this, 'changePriceType')}></Radio>
|
||||
</div>
|
||||
</div> */}
|
||||
{/* 禁用网络打印 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">禁用网络打印机:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
{value: 0, text: '否'},
|
||||
{value: 1, text: '是'}
|
||||
]} id={'printerDisabled'} current={this.state.printerDisabled} fnClick={this.handleModify.bind(this, 'printerDisabled')}></Radio>
|
||||
</div>
|
||||
</div>
|
||||
{/* 打印机类型 */}
|
||||
<div className="create-cell printer-cell">
|
||||
<div className="cell-label">打印机品牌:</div>
|
||||
<div className="printer" onClick={this.fnPrinterVendorID.bind(this)}>{this.dealPrinterVendorID(this.state.printerVendorID)}</div>
|
||||
<div></div>
|
||||
</div>
|
||||
{/* 网络打印机SN */}
|
||||
{
|
||||
this.state.printerVendorID !== 0 && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">{this.state.printerInfo[1]}</div>
|
||||
<Input ref="printerSN" fnBlur={this.handleModify.bind(this, 'printerSN')} value={this.state.printerSN} placeholder={'请填写' + this.state.printerInfo[1]}></Input>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 网络打印机KEY */}
|
||||
{
|
||||
(this.state.printerVendorID !== 0 && this.state.printerInfo[2] !== '不填') && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">{this.state.printerInfo[2]}</div>
|
||||
<Input ref="printerKey" fnBlur={this.handleModify.bind(this, 'printerKey')} value={this.state.printerKey} placeholder={'请填写' + this.state.printerInfo[2]}></Input>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className="header-title">地址及配送范围</div>
|
||||
{/* 所在城市 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">所在城市:</div>
|
||||
<div className="cell-city">
|
||||
<div className="area" onClick={this.fnCityPick.bind(this)}>{cityName}</div>
|
||||
<div className="area" onClick={this.fnDistrictPick.bind(this)}>{districtName}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* 详细地址 */}
|
||||
<div className="create-cell" onClick={this.showMap.bind(this)}>
|
||||
<div className="cell-label">详细地址:</div>
|
||||
<div className="cell-value">{this.state.address || '请填写详细地址'}</div>
|
||||
<ReactSVG src={SVGGo} className="icon"></ReactSVG>
|
||||
</div>
|
||||
{/* 配送范围 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">配送范围:</div>
|
||||
<div className="cell-value">
|
||||
<Radio fields={[
|
||||
// {value: 2, text: '规划范围'},
|
||||
{value: 3, text: '半径服务'}
|
||||
]} id={'changePriceType'} current={this.state.deliveryRangeType} fnClick={this.handleModify.bind(this, 'deliveryRangeType')}></Radio>
|
||||
<Input ref="deliveryRange" className="rangeInput" check={isNum} errText="半径不合法" fnBlur={this.handleModify.bind(this, 'deliveryRange')} value={this.state.deliveryRange} placeholder="请输入半径" type="number"></Input>
|
||||
<div className="suffix">米</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="padding-bottom-1rem"></div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 时间checkList */}
|
||||
<CheckList ref="openTime1" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.openTime1} title="开始时间" fnPick={this.handleModify.bind(this, 'openTime1')}></CheckList>
|
||||
<CheckList ref="closeTime1" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.closeTime1} title="结束时间" fnPick={this.handleModify.bind(this, 'closeTime1')}></CheckList>
|
||||
<CheckList ref="openTime2" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.openTime2} title="开始时间" fnPick={this.handleModify.bind(this, 'openTime2')}></CheckList>
|
||||
<CheckList ref="closeTime2" datas={this.timeList} map={{value: 'value', label: 'label'}} current={this.state.closeTime2} title="结束时间" fnPick={this.handleModify.bind(this, 'closeTime2')}></CheckList>
|
||||
<CheckList ref="printerVendorID" datas={this.state.printerVendorInfoArr} map={{value: 'value', label: 'label'}} current={this.state.printerVendorID} title="网络打印机品牌" fnPick={this.handleModify.bind(this, 'printerVendorID')}></CheckList>
|
||||
{/* 市、区选择 */}
|
||||
<CheckList ref="cityCode" datas={this.props.system.cityLevel2} map={{value: 'code', label: 'name'}} current={this.state.cityCode} title="选择市" fnPick={this.handleModify.bind(this, 'cityCode')}></CheckList>
|
||||
<CheckList ref="districtCode" datas={this.state.districtData} map={{value: 'code', label: 'name'}} current={this.state.districtCode} title="选择区" fnPick={this.handleModify.bind(this, 'districtCode')}></CheckList>
|
||||
{/* 详细地址 */}
|
||||
<SearchAddress ref="SearchAddress" region={cityData ? cityData.name : ''} fnPick={this.addressPick.bind(this)}></SearchAddress>
|
||||
</PopupPage>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect((state, props) => Object.assign({}, props, state), {})(CreateStore);
|
||||
94
src/components/pageCmp/Input.js
Normal file
94
src/components/pageCmp/Input.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
// import Toast from '@/components/Toast';
|
||||
|
||||
/*
|
||||
check={isNum} 校验函数
|
||||
value={this.state.id} 默认值
|
||||
placeholder=""
|
||||
errText="京西门店ID必须是纯数字" 报错提示
|
||||
fnBlur={this.idBlur.bind(this, key)} 失去焦点处理函数 可以为空
|
||||
*/
|
||||
|
||||
class Input extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
wrongShow: false
|
||||
};
|
||||
}
|
||||
componentDidMount () {
|
||||
// console.log('校······验', this.props.value)
|
||||
// 校验一次defaultValue
|
||||
this.props.check && this.setState({wrongShow: !this.props.check(this.props.value)});
|
||||
}
|
||||
// 当props或者state变化时才更新
|
||||
// shouldComponentUpdate (nextProps, nextState) {
|
||||
// // console.log(JSON.stringify(nextProps) !== JSON.stringify(this.props) || JSON.stringify(nextState) !== JSON.stringify(this.state))
|
||||
// return JSON.stringify(nextProps) !== JSON.stringify(this.props) || JSON.stringify(nextState) !== JSON.stringify(this.state);
|
||||
// }
|
||||
// 更新触发校验
|
||||
// componentDidUpdate () {
|
||||
// this.props.check && this.setState({wrongShow: !this.props.check(this.props.value)});
|
||||
// }
|
||||
// id变化
|
||||
storeIDChange (e) {
|
||||
// console.log(e.target.value);
|
||||
this.props.check && this.setState({wrongShow: !this.props.check(e.target.value.trim())});
|
||||
|
||||
if (this.props.check) {
|
||||
this.setState({wrongShow: !this.props.check(e.target.value.trim())});
|
||||
if (this.props.check(e.target.value.trim())) {
|
||||
this.props.fnBlur && this.props.fnBlur(e.target.value.trim());
|
||||
} else {
|
||||
this.setState({wrongShow: true});
|
||||
this.props.fnBlur && this.props.fnBlur(e.target.value.trim());
|
||||
}
|
||||
}
|
||||
this.props.fnBlur && this.props.fnBlur(e.target.value.trim());
|
||||
}
|
||||
// id失去焦点
|
||||
storeIDBlue (e) {
|
||||
// console.log(e.target.value)
|
||||
// !isNum(e.target.value) ? Toast.show('京西门店ID需要纯数字') : this.
|
||||
if (this.props.check) {
|
||||
if (this.props.check(e.target.value.trim())) {
|
||||
this.props.fnBlur && this.props.fnBlur(e.target.value.trim());
|
||||
} else {
|
||||
this.setState({wrongShow: true});
|
||||
this.props.fnBlur && this.props.fnBlur(e.target.value.trim());
|
||||
|
||||
// Toast.show(this.props.errText);
|
||||
}
|
||||
} else {
|
||||
this.props.fnBlur && this.props.fnBlur(e.target.value.trim());
|
||||
}
|
||||
}
|
||||
// 校验
|
||||
checkData () {
|
||||
// console.log('校验');
|
||||
this.refs.input.value = this.props.value;
|
||||
this.props.check && this.setState({wrongShow: !this.props.check(this.props.value)});
|
||||
}
|
||||
// 清除
|
||||
fnClear () {
|
||||
this.refs.input.value = '';
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<input
|
||||
ref="input"
|
||||
type={this.props.type || 'text'}
|
||||
className={classNames('cell-input', {'danger': this.state.wrongShow}, this.props.className)}
|
||||
placeholder={this.props.placeholder}
|
||||
defaultValue={this.props.value}
|
||||
onChange={this.storeIDChange.bind(this)}
|
||||
onBlur={this.storeIDBlue.bind(this)}
|
||||
onClick={this.props.onClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Input;
|
||||
141
src/components/pageCmp/ModifyStore.js
Normal file
141
src/components/pageCmp/ModifyStore.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import React, { Component } from 'react';
|
||||
import './modify-store.scss';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
|
||||
import SVGStore from '@/assets/svg/icon-store.svg';
|
||||
import PopupPage from '@/components/layout/PopupPage';
|
||||
import Dialog from '@/components/Dialog';
|
||||
import Loading from '@/components/Loading';
|
||||
import Tabs from '@/components/layout/Tabs';
|
||||
// import BScroll from 'better-scroll';
|
||||
import CmpModifyBase from '@/components/pageCmp/CmpModifyBase'
|
||||
import CmpModifyMaps from '@/components/pageCmp/CmpModifyMaps'
|
||||
import CmpModifyGroup from '@/components/pageCmp/CmpModifyGroup'
|
||||
|
||||
class ModifyStore extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
shop: {},
|
||||
users: [],
|
||||
current: 0
|
||||
};
|
||||
// this.scroll = null;
|
||||
}
|
||||
async componentDidMount () {
|
||||
await this.getStore();
|
||||
await this.getStoreUsers();
|
||||
// 增加滚动
|
||||
// this.scroll = new BScroll(this.refs.modifyWrapper, {
|
||||
// // click: true,
|
||||
// bounce: {
|
||||
// top: false,
|
||||
// bottom: false
|
||||
// }
|
||||
// });
|
||||
}
|
||||
// 获取门店数据
|
||||
async getStore () {
|
||||
try {
|
||||
Loading.show();
|
||||
let {stores} = await fetchJson('/v2/store/GetStores?storeID=' + this.props.shop.id);
|
||||
console.log('当前门店', stores[0]);
|
||||
await this.setState({shop: stores[0]});
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span calss="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 获取分组数据
|
||||
async getStoreUsers () {
|
||||
try {
|
||||
Loading.show();
|
||||
let res = await fetchJson('/v2/user2/GetRoleUserList?roleName=StoreBoss&storeID=' + this.props.shop.id);
|
||||
if (res) {
|
||||
let users = await this.apiGetUserList(res);
|
||||
this.setState({users});
|
||||
} else {
|
||||
this.setState({users: []});
|
||||
}
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span calss="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 获取所有用户列表
|
||||
apiGetUserList = async (userIDs = [], pageSize = 50) => {
|
||||
try {
|
||||
let {data} = await fetchJson(`/v2/user2/GetUsers?userIDs=${JSON.stringify(userIDs)}&userType=14&offset=0&pageSize=50`)
|
||||
// console.log('获取的用户', totalCount, data)
|
||||
console.log('用户信息', data);
|
||||
return data || []
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
Dialog.show('错误', `<span calss="error">${e}</span>`, {showCancel: false});
|
||||
}
|
||||
}
|
||||
// tabs切换
|
||||
async fnSwitch (index) {
|
||||
// console.log(index);
|
||||
this.setState({current: index});
|
||||
if (index !== 2) {
|
||||
await this.getStore();
|
||||
} else {
|
||||
await this.getStoreUsers();
|
||||
}
|
||||
}
|
||||
componentDidUpdate () {
|
||||
console.log('updated')
|
||||
// this.scroll = new BScroll(this.refs.modifyWrapper, {
|
||||
// // click: true,
|
||||
// // stopPropagation: true,
|
||||
// bounce: {
|
||||
// top: false,
|
||||
// bottom: false
|
||||
// }
|
||||
// });
|
||||
// this.scroll && this.scroll.refresh();
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="modify-store">
|
||||
<PopupPage
|
||||
title={this.props.shop.name}
|
||||
fnReturn={this.props.fnReturn}
|
||||
showConfirm={false}
|
||||
SVG={SVGStore}
|
||||
>
|
||||
<Tabs
|
||||
current={this.state.current}
|
||||
fields={[
|
||||
{index: 0, text: '基础信息'},
|
||||
{index: 1, text: '平台绑定'},
|
||||
{index: 2, text: '分组管理'}
|
||||
]}
|
||||
fnClick={this.fnSwitch.bind(this)}
|
||||
></Tabs>
|
||||
{
|
||||
this.state.current === 0 && this.state.shop.id && <div className="modify-body">
|
||||
<CmpModifyBase shop={this.state.shop}></CmpModifyBase>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
this.state.current === 1 && this.state.shop.id && <div className="modify-body">
|
||||
<CmpModifyMaps shop={this.state.shop} update={this.getStore.bind(this)}></CmpModifyMaps>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
this.state.current === 2 && this.state.shop.id && <div className="modify-body">
|
||||
<CmpModifyGroup storeID={this.state.shop.id} users={this.state.users} update={this.getStoreUsers.bind(this)}></CmpModifyGroup>
|
||||
</div>
|
||||
}
|
||||
</PopupPage>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ModifyStore;
|
||||
206
src/components/pageCmp/MoreSearch.js
Normal file
206
src/components/pageCmp/MoreSearch.js
Normal file
@@ -0,0 +1,206 @@
|
||||
import React, { Component } from 'react';
|
||||
import PopupPage from '@/components/layout/PopupPage';
|
||||
import {connect} from 'react-redux';
|
||||
import {setStoreSearch} from '@/store/actions';
|
||||
import './more-search.scss';
|
||||
import ReactSVG from 'react-svg'
|
||||
import SVGGo from '@/assets/svg/icon-go.svg';
|
||||
|
||||
import Radio from '@/components/layout/Radio';
|
||||
import CheckBox from '@/components/layout/CheckBox';
|
||||
import CheckList from '@/components/layout/CheckList';
|
||||
|
||||
class MoreSearch extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.state = {};
|
||||
this.vendorList = [
|
||||
{id: 0, name: '京东'},
|
||||
{id: 1, name: '美团'},
|
||||
{id: 3, name: '饿百'},
|
||||
{id: 9, name: '京西'},
|
||||
// {id: 11, name: '微盟'}
|
||||
];
|
||||
this.courierList = [
|
||||
{id: 101, name: '达达'},
|
||||
{id: 102, name: '美团'}
|
||||
];
|
||||
this.fields = [
|
||||
{value: 0, text: '不限定'},
|
||||
{value: 1, text: '已绑定'},
|
||||
{value: -1, text: '未绑定'}
|
||||
];
|
||||
this.fieldsStore = [
|
||||
{value: '0', text: '不限定'},
|
||||
{value: '1', text: '已绑定'},
|
||||
{value: '-1', text: '未绑定'}
|
||||
];
|
||||
}
|
||||
async componentDidMount () {
|
||||
await this.setState({
|
||||
...this.props.search.storeSearch
|
||||
});
|
||||
// console.log(this.props.system.vendorOrgCode)
|
||||
}
|
||||
// 平台门店绑定情况切换
|
||||
vendorStoreCondsClick (val, id) {
|
||||
console.log(val, id);
|
||||
this.setState({
|
||||
vendorStoreConds: {
|
||||
...this.state.vendorStoreConds,
|
||||
[id]: val
|
||||
}
|
||||
});
|
||||
}
|
||||
// 平台门店绑定情况切换
|
||||
courierStoreCondsClick (val, id) {
|
||||
// console.log(val, id);
|
||||
this.setState({
|
||||
courierStoreConds: {
|
||||
...this.state.courierStoreConds,
|
||||
[id]: val
|
||||
}
|
||||
});
|
||||
}
|
||||
// 点击确定
|
||||
async fnConfirm () {
|
||||
console.log(this.state);
|
||||
await this.props.setStoreSearch(this.state)
|
||||
this.props.fnConfirm && this.props.fnConfirm();
|
||||
}
|
||||
// 营业状态修改
|
||||
changeStatuss (val) {
|
||||
// console.log(val);
|
||||
let arr = Object.assign([], this.state.statuss);
|
||||
// 查找元素
|
||||
let n = arr.indexOf(val);
|
||||
if (n === -1) {
|
||||
// 没找到,添加
|
||||
arr.push(val);
|
||||
} else {
|
||||
// 找到了,去除
|
||||
if (arr.length !== 1) arr.splice(n, 1);
|
||||
}
|
||||
this.setState({
|
||||
statuss: arr
|
||||
});
|
||||
}
|
||||
// 城市改变
|
||||
changeCity () {
|
||||
console.log('城市改变');
|
||||
this.refs.checklist.show();
|
||||
}
|
||||
// 选择城市
|
||||
cityPick (val) {
|
||||
console.log(val);
|
||||
this.setState({placeID: Number(val)});
|
||||
}
|
||||
dealVendorOrgCode = (list, vendor) => {
|
||||
let arr = JSON.parse(JSON.stringify(list))
|
||||
const {vendorOrgCode} = this.props.system
|
||||
// console.log(arr, vendor, vendorOrgCode, )
|
||||
let account = vendorOrgCode[vendor.id]
|
||||
if (account && account.length > 1) {
|
||||
account.forEach(item => {
|
||||
arr.push({
|
||||
value: item,
|
||||
text: item
|
||||
})
|
||||
})
|
||||
}
|
||||
return arr
|
||||
}
|
||||
// 渲染
|
||||
render() {
|
||||
let storeSearch = this.state;
|
||||
let placeName = storeSearch.placeID ? this.props.system.cityLevel2.find(item => item.code === storeSearch.placeID).name : '全国';
|
||||
return (
|
||||
<div className="more-search">
|
||||
{
|
||||
// 存在才渲染
|
||||
storeSearch.vendorStoreConds && (
|
||||
<PopupPage
|
||||
className="more-search"
|
||||
title="更多检索条件"
|
||||
fnReturn={this.props.fnReturn.bind(this)}
|
||||
fnConfirm={this.fnConfirm.bind(this)}
|
||||
>
|
||||
{/* 城市 */}
|
||||
<div className="search-cell" onClick={this.changeCity.bind(this)}>
|
||||
<div className="cell-label">城市:</div>
|
||||
<div className="cell-value">{placeName}</div>
|
||||
<ReactSVG src={SVGGo} className="icon"></ReactSVG>
|
||||
</div>
|
||||
{/* 营业状态 */}
|
||||
<div className="search-cell">
|
||||
<div className="cell-label">状态:</div>
|
||||
<div className="cell-value">
|
||||
<CheckBox
|
||||
current={storeSearch.statuss}
|
||||
fields={[
|
||||
{value: 1, text: '营业'},
|
||||
{value: 0, text: '临时休息'},
|
||||
{value: -1, text: '长期休息'},
|
||||
{value: -2, text: '禁用'}
|
||||
]}
|
||||
fnClick={this.changeStatuss.bind(this)}
|
||||
></CheckBox>
|
||||
</div>
|
||||
</div>
|
||||
{/* 平台门店绑定情况 */}
|
||||
<div className="header-title">平台门店绑定情况</div>
|
||||
{/* cell */}
|
||||
{
|
||||
this.vendorList.map((item, index) => (
|
||||
<div className="search-cell" key={index}>
|
||||
<div className="cell-label">{item.name}:</div>
|
||||
<div className="cell-value">
|
||||
<Radio
|
||||
fields={this.dealVendorOrgCode(this.fieldsStore, item)}
|
||||
current={storeSearch.vendorStoreConds[item.id]}
|
||||
id={item.id}
|
||||
fnClick={this.vendorStoreCondsClick.bind(this)}
|
||||
></Radio>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{/* cell */}
|
||||
{/* 专送门店绑定情况 */}
|
||||
<div className="header-title">专送门店绑定情况</div>
|
||||
{
|
||||
this.courierList.map((item, index) => (
|
||||
<div className="search-cell" key={index}>
|
||||
<div className="cell-label">{item.name}:</div>
|
||||
<div className="cell-value">
|
||||
<Radio
|
||||
fields={this.fields}
|
||||
current={storeSearch.courierStoreConds[item.id]}
|
||||
id={item.id}
|
||||
fnClick={this.courierStoreCondsClick.bind(this)}
|
||||
></Radio>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</PopupPage>
|
||||
)
|
||||
}
|
||||
{/* checkList */}
|
||||
<CheckList
|
||||
ref="checklist"
|
||||
datas={this.props.system.cityLevel2}
|
||||
map={{value: 'code', label: 'name'}}
|
||||
nullShow={true}
|
||||
nullLabel='全国'
|
||||
current={storeSearch.placeID}
|
||||
title="城市选择"
|
||||
fnPick={this.cityPick.bind(this)}
|
||||
></CheckList>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect((state, props) => Object.assign({}, props, state), {setStoreSearch})(MoreSearch);
|
||||
39
src/components/pageCmp/StoreCell.js
Normal file
39
src/components/pageCmp/StoreCell.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import React, { Component } from 'react';
|
||||
import classNames from 'classnames'
|
||||
import './store-cell.scss';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
class StoreCell extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.storeStatus = {
|
||||
'-1': '长期休息',
|
||||
'0': '临时休息',
|
||||
'1': '营业',
|
||||
'-2': '禁用'
|
||||
}
|
||||
}
|
||||
render() {
|
||||
let store = this.props.shop;
|
||||
// 门店所在城市
|
||||
let cityData = this.props.system.cityLevel2.find(item => item.code === store.cityCode);
|
||||
let cityName = cityData ? cityData.name : '未知'
|
||||
return (
|
||||
<div className="store-item" onClick={this.props.onClick}>
|
||||
<div className="store-cell">
|
||||
{/* <div className="store-id">{store.id}</div> */}
|
||||
<div className="store-name">
|
||||
{store.name}
|
||||
<span className="city">({cityName})
|
||||
</span>
|
||||
</div>
|
||||
{/* 营业状态 */}
|
||||
<div className={classNames('store-status', {'status-jy': store.status < 0}, {'status-xx': store.status === 0}, {'status-yy': store.status === 1})}>{this.storeStatus[store.status]}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect((state, props) => Object.assign({}, props, state), {})(StoreCell);
|
||||
462
src/components/pageCmp/VendorCell.js
Normal file
462
src/components/pageCmp/VendorCell.js
Normal file
@@ -0,0 +1,462 @@
|
||||
import React, {Component} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import {connect} from 'react-redux';
|
||||
import ReactSVG from 'react-svg';
|
||||
import {isNum} from '@/utils/regExp';
|
||||
import Loading from '@/components/Loading';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
|
||||
import SVGInsert from '@/assets/svg/icon-insert.svg';
|
||||
import SVGDelete from '@/assets/svg/icon-delete.svg';
|
||||
import SVGUpdate from '@/assets/svg/icon-update.svg';
|
||||
|
||||
import PopupPage from '@/components/layout/PopupPage';
|
||||
import CheckBoxSelf from '@/components/layout/CheckBoxSelf';
|
||||
import Radio from '@/components/layout/Radio';
|
||||
import Input from '@/components/pageCmp/Input';
|
||||
import Dialog from '@/components/Dialog';
|
||||
import CheckList from '@/components/layout/CheckList';
|
||||
|
||||
/*
|
||||
shop={this.state}
|
||||
plant={{name: 'StoreMaps', id: 1}}
|
||||
*/
|
||||
|
||||
class VendorCell extends Component {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
let vendorOrgCodeArr = this.props.system.vendorOrgCode[this.props.plant.id]
|
||||
this.reset = {
|
||||
vendorStoreID: '',
|
||||
status: 1, // 开关店状态
|
||||
vendorID: this.props.plant.id,
|
||||
autoPickup: 1, // 是否自动拣货
|
||||
deliveryCompetition: 1, // 是否配送竞争
|
||||
pricePercentage: 100,
|
||||
isSync: 1, // 是否同步
|
||||
popupShow: false,
|
||||
isEditor: false,
|
||||
vendorOrgCode: this.props.plant.id < 100 ? vendorOrgCodeArr[0] : ''
|
||||
};
|
||||
this.state = {
|
||||
vendorStoreID: '',
|
||||
status: 1, // 开关店状态
|
||||
vendorID: this.props.plant.id,
|
||||
autoPickup: 1, // 是否自动拣货
|
||||
deliveryCompetition: 1, // 是否配送竞争
|
||||
pricePercentage: 100,
|
||||
isSync: 1, // 是否同步
|
||||
popupShow: false,
|
||||
isEditor: false,
|
||||
vendorOrgCode: this.props.plant.id < 100 ? vendorOrgCodeArr[0] : ''
|
||||
};
|
||||
this.vendorOrgCodeList = []
|
||||
if (vendorOrgCodeArr) {
|
||||
vendorOrgCodeArr.forEach(item => {
|
||||
this.vendorOrgCodeList.push({
|
||||
code: item,
|
||||
name: item
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
componentDidMount () {
|
||||
console.log('vendorOrgCode', this.props.system.vendorOrgCode, this.props.plant.id)
|
||||
}
|
||||
// 远程查询平台门店信息
|
||||
async searchVendorStore () {
|
||||
try {
|
||||
Loading.show();
|
||||
let res = await fetchJson(`/v2/store/GetVendorStore?vendorStoreID=${this.state.vendorStoreID}&vendorID=${this.state.vendorID}&vendorOrgCode=${this.state.vendorOrgCode}`);
|
||||
console.log(res);
|
||||
Dialog.show('平台门店查询成功', `<p class="success">${res.cityName}${res.districtName}${res.name}</p><p class="address">${res.address}</p>`, {showCancel: false});
|
||||
} catch (e) {
|
||||
// console.error(e);
|
||||
Dialog.show('查询错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 获取平台门店绑定情况
|
||||
async getVendorMaps () {
|
||||
try {
|
||||
Loading.show();
|
||||
let res = await fetchJson('/v2/store/GetStoreVendorMaps?storeID=' + this.props.shop.id + '&vendorID=' + this.state.vendorID);
|
||||
await this.setState({
|
||||
...this.state,
|
||||
...res[0]
|
||||
});
|
||||
console.log('平台门店绑定情况', res[0]);
|
||||
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 获取专送门店绑定情况
|
||||
async getCourierMaps () {
|
||||
try {
|
||||
Loading.show();
|
||||
let res = await fetchJson('/v2/store/GetStoreCourierMaps?storeID=' + this.props.shop.id + '&vendorID=' + this.state.vendorID);
|
||||
await this.setState({
|
||||
...this.state,
|
||||
...res[0]
|
||||
});
|
||||
console.log('平台门店绑定情况', res[0]);
|
||||
|
||||
} catch (e) {
|
||||
Dialog.show('错误', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
// 绑定
|
||||
fnBind () {
|
||||
console.log('绑定');
|
||||
this.setState({popupShow: true});
|
||||
}
|
||||
// 删除绑定
|
||||
async fnDelete () {
|
||||
console.log('删除');
|
||||
Dialog.show('警告', `是否解除${this.props.shop.name}-${this.props.system.cms.vendorName[this.props.plant.id]}的绑定`, {}, async (res) => {
|
||||
if (res) {
|
||||
try {
|
||||
Loading.show();
|
||||
if (this.state.vendorID < 100) {
|
||||
await fetchJson(`/v2/store/DeleteStoreVendorMap?storeID=${this.props.shop.id}&vendorID=${this.state.vendorID}`, {method: 'DELETE'});
|
||||
} else {
|
||||
await fetchJson(`/v2/store/DeleteStoreCourierMap?storeID=${this.props.shop.id}&vendorID=${this.state.vendorID}`, {method: 'DELETE'});
|
||||
}
|
||||
Dialog.show('成功', `<span class="success">解绑成功</span>`, {showCancel: false});
|
||||
// 更新数据
|
||||
this.props.update && this.props.update();
|
||||
} catch (e) {
|
||||
Dialog.show('解绑失败', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 点击编辑
|
||||
async fnUpdate () {
|
||||
console.log('编辑');
|
||||
if (this.state.vendorID < 100) {
|
||||
// 平台门店绑定
|
||||
await this.getVendorMaps();
|
||||
} else {
|
||||
// 专送门店绑定
|
||||
await this.getCourierMaps();
|
||||
}
|
||||
console.log(this.state);
|
||||
this.setState({popupShow: true, isEditor: true});
|
||||
}
|
||||
// 弹出框返回
|
||||
fnReturn () {
|
||||
// this.setState({popupShow: false, isEditor: false});
|
||||
console.log('重置数据');
|
||||
this.setState({...this.reset});
|
||||
}
|
||||
// 弹出框验证 新增、编辑
|
||||
async fnPrevConfirm () {
|
||||
console.log(this.state);
|
||||
// 存放错误消息
|
||||
let arr = [];
|
||||
if (!isNum(this.state.vendorStoreID)) arr.push('平台门店ID必须是纯数字');
|
||||
if (!isNum(this.state.pricePercentage)) arr.push('平台调价必须是纯数字');
|
||||
if (arr.length > 0) {
|
||||
Dialog.show('错误', `<span class="error">${arr.join('<br />')}</span>`, {
|
||||
showCancel: false,
|
||||
confirmText: '好的'
|
||||
})
|
||||
return false;
|
||||
} else {
|
||||
// 请求接口绑定门店
|
||||
console.log('开始保存');
|
||||
try {
|
||||
Loading.show();
|
||||
let form = new FormData();
|
||||
form.append('storeID', this.props.shop.id);
|
||||
form.append('vendorID', this.state.vendorID);
|
||||
if (this.state.isEditor) {
|
||||
// ----- 编辑 -----
|
||||
if (this.state.vendorID < 100) {
|
||||
form.append('vendorOrgCode', this.state.vendorOrgCode)
|
||||
// 平台编辑
|
||||
let json = {
|
||||
autoPickup: this.state.autoPickup,
|
||||
deliveryCompetition: this.state.deliveryCompetition,
|
||||
isSync: this.state.isSync,
|
||||
pricePercentage: this.state.pricePercentage,
|
||||
status: this.state.status,
|
||||
syncStatus: this.state.syncStatus,
|
||||
vendorStoreID: this.state.vendorStoreID,
|
||||
vendorOrgCode: this.state.vendorOrgCode
|
||||
}
|
||||
form.append('payload', JSON.stringify(json));
|
||||
await fetchJson('/v2/store/UpdateStoreVendorMap', {
|
||||
method: 'PUT',
|
||||
body: form
|
||||
});
|
||||
} else {
|
||||
// 专送编辑
|
||||
let json = {
|
||||
vendorStoreID: this.state.vendorStoreID,
|
||||
status: this.state.status
|
||||
}
|
||||
form.append('payload', JSON.stringify(json));
|
||||
await fetchJson('/v2/store/UpdateStoreCourierMap', {
|
||||
method: 'PUT',
|
||||
body: form
|
||||
});
|
||||
}
|
||||
|
||||
// console.log(res);
|
||||
Dialog.show('成功', `<span class="success">修改成功</span>`, {showCancel: false});
|
||||
return true;
|
||||
} else {
|
||||
// ----- 新增 -----
|
||||
if (this.state.vendorID < 100) {
|
||||
form.append('vendorOrgCode', this.state.vendorOrgCode)
|
||||
// 新增平台
|
||||
let json = {
|
||||
vendorStoreID: this.state.vendorStoreID,
|
||||
status: this.state.status,
|
||||
autoPickup: this.state.Pickup,
|
||||
deliveryCompetition: this.state.deliveryCompetition,
|
||||
pricePercentage: Number(this.state.pricePercentage),
|
||||
isSync: this.state.isSync,
|
||||
vendorOrgCode: this.state.vendorOrgCode
|
||||
}
|
||||
form.append('payload', JSON.stringify(json));
|
||||
await fetchJson('/v2/store/AddStoreVendorMap', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
} else {
|
||||
// 新增专送
|
||||
let json = {
|
||||
vendorStoreID: this.state.vendorStoreID,
|
||||
status: this.state.status
|
||||
}
|
||||
form.append('payload', JSON.stringify(json));
|
||||
await fetchJson('/v2/store/AddStoreCourierMap', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
}
|
||||
|
||||
Dialog.show('成功', `<span class="success">绑定成功</span>`, {showCancel: false});
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
Dialog.show('绑定失败', `<span class="error">${e}</span>`, {showCancel: false});
|
||||
} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 弹出框确定
|
||||
fnConfirm () {
|
||||
// this.setState({popupShow: false, isEditor: false});
|
||||
this.setState({...this.reset});
|
||||
// 更新数据
|
||||
this.props.update && this.props.update();
|
||||
}
|
||||
// 修改
|
||||
handleModify (key, val) {
|
||||
console.log(key, val);
|
||||
this.setState({[key]: val});
|
||||
}
|
||||
// 切换账号
|
||||
fnOrgCodePick = () => {
|
||||
this.refs.orgCode.show();
|
||||
}
|
||||
// 修改账号
|
||||
render () {
|
||||
let plantData = null;
|
||||
if (this.props.shop[this.props.plant.name]) {
|
||||
plantData = this.props.shop[this.props.plant.name].find(item => item.vendorID === this.props.plant.id);
|
||||
}
|
||||
let venderName = this.props.system.cms.vendorName ? this.props.system.cms.vendorName[this.props.plant.id] : '';
|
||||
return (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">{venderName}:</div>
|
||||
<div className={classNames(
|
||||
'cell-text',
|
||||
{'no-bind': !plantData},
|
||||
{'status-0': plantData && plantData.status === 0},
|
||||
{'status-1': plantData && plantData.status === 1}
|
||||
)}>{plantData ? plantData.vendorStoreID : '未绑定'}</div>
|
||||
{/* 添加绑定 */}
|
||||
{
|
||||
!plantData && (
|
||||
<div className="btn-insert" onClick={this.fnBind.bind(this)}>
|
||||
<ReactSVG className="svg" src={SVGInsert}></ReactSVG>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 删除绑定 */}
|
||||
{
|
||||
plantData && (
|
||||
<div className="btn-delete" onClick={this.fnDelete.bind(this)}>
|
||||
<ReactSVG className="svg" src={SVGDelete}></ReactSVG>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 修改绑定 */}
|
||||
{
|
||||
plantData && (
|
||||
<div className="btn-update" onClick={this.fnUpdate.bind(this)}>
|
||||
<ReactSVG className="svg" src={SVGUpdate}></ReactSVG>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 添加编辑弹出框 */}
|
||||
{
|
||||
this.state.popupShow && (
|
||||
<PopupPage
|
||||
className="cmp-modify-maps"
|
||||
title={this.state.isEditor ? '编辑' + venderName : '绑定' + venderName}
|
||||
fnReturn={this.fnReturn.bind(this)}
|
||||
fnPrevConfirm={this.fnPrevConfirm.bind(this)}
|
||||
showConfirm={true}
|
||||
fnConfirm={this.fnConfirm.bind(this)}
|
||||
>
|
||||
<div className="header-title">正在操作 {this.props.shop.name} {this.state.isEditor ? '编辑' : '绑定'} {venderName}</div>
|
||||
{/* 平台status */}
|
||||
{
|
||||
this.state.isEditor && this.state.vendorID < 100 && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">平台状态:</div>
|
||||
<div className="cell-value-checkbox">
|
||||
<Radio fields={[
|
||||
{value: 1, text: '开店'},
|
||||
{value: 0, text: '关店'}
|
||||
]} id={'status'} current={this.state.status} fnClick={this.handleModify.bind(this, 'status')}></Radio>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 平台账号 */}
|
||||
{
|
||||
!this.state.isEditor && this.state.vendorID < 100 && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">平台账号:</div>
|
||||
<div className="btn-wrapper">
|
||||
<div className="orgCode" onClick={this.fnOrgCodePick}>{this.state.vendorOrgCode}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 平台门店ID */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">平台门店ID:</div>
|
||||
{
|
||||
this.state.isEditor ? (
|
||||
<div className="cell-vendorStoreID-text">{this.state.vendorStoreID}</div>
|
||||
) : (
|
||||
<Input className="rangeInput" check={isNum} errText="平台门店ID不合法" fnBlur={this.handleModify.bind(this, 'vendorStoreID')} value={this.state.vendorStoreID} placeholder="请输入平台门店ID"></Input>
|
||||
)
|
||||
}
|
||||
{
|
||||
this.state.vendorID < 100 ? (
|
||||
<div className="suffix-btn" onClick={this.searchVendorStore.bind(this)}>查询</div>
|
||||
) : ''
|
||||
}
|
||||
</div>
|
||||
{
|
||||
this.state.vendorID < 100 ? (
|
||||
<div>
|
||||
{/* 基本设置 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">基本设置:</div>
|
||||
<div className="cell-value">
|
||||
<CheckBoxSelf
|
||||
className="base-setting"
|
||||
current={this.state.autoPickup}
|
||||
text="自动拣货"
|
||||
fields={[0, 1]}
|
||||
fnClick={this.handleModify.bind(this, 'autoPickup')}
|
||||
></CheckBoxSelf>
|
||||
<CheckBoxSelf
|
||||
className="base-setting"
|
||||
current={this.state.deliveryCompetition}
|
||||
text="配送竞争"
|
||||
fields={[0, 1]}
|
||||
fnClick={this.handleModify.bind(this, 'deliveryCompetition')}
|
||||
></CheckBoxSelf>
|
||||
</div>
|
||||
</div>
|
||||
{/* 平台调价 */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">平台调价:</div>
|
||||
<Input className="rangeInput" check={isNum} errText="请输入纯数字的平台调价" fnBlur={this.handleModify.bind(this, 'pricePercentage')} value={this.state.pricePercentage} placeholder="百分数"></Input>
|
||||
<div className="suffix-text">%</div>
|
||||
</div>
|
||||
{/* 同步状态 */}
|
||||
{/* {
|
||||
!this.state.isEditor && (
|
||||
|
||||
)
|
||||
} */}
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">同步状态:</div>
|
||||
<div className="cell-value-checkbox">
|
||||
{
|
||||
!this.state.isEditor && (
|
||||
<Radio fields={[
|
||||
{value: 1, text: '同步'},
|
||||
{value: 0, text: '不同步'}
|
||||
]} id={'isSync'} current={this.state.isSync} fnClick={this.handleModify.bind(this, 'isSync')}></Radio>
|
||||
)
|
||||
}
|
||||
{
|
||||
this.state.isEditor && this.state.isSync ? (
|
||||
<span>同步</span>
|
||||
) : (
|
||||
<Radio fields={[
|
||||
{value: 1, text: '同步'},
|
||||
{value: 0, text: '不同步'}
|
||||
]} id={'isSync'} current={this.state.isSync} fnClick={this.handleModify.bind(this, 'isSync')}></Radio>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{/* 配送类型 */}
|
||||
{
|
||||
this.state.isEditor && (
|
||||
<div className="create-cell">
|
||||
<div className="cell-label">快递类型:</div>
|
||||
<div className="cell-vendorStoreID-text">
|
||||
{this.props.system.cms.storeDeliveryType[this.state.deliveryType]}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
) : (
|
||||
<div className="create-cell">
|
||||
{/* 专送status */}
|
||||
<div className="cell-label">状态:</div>
|
||||
<div className="cell-value-checkbox">
|
||||
<Radio fields={[
|
||||
{value: 1, text: '开启'},
|
||||
{value: 0, text: '关闭'}
|
||||
]} id={'status'} current={this.state.status} fnClick={this.handleModify.bind(this, 'status')}></Radio>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 账号选择 */}
|
||||
<CheckList ref="orgCode" datas={this.vendorOrgCodeList} map={{value: 'code', label: 'name'}} current={this.state.vendorOrgCode} title="选择账号" fnPick={this.handleModify.bind(this, 'vendorOrgCode')}></CheckList>
|
||||
</PopupPage>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default connect((state, props) => Object.assign({}, props, state), {})(VendorCell);
|
||||
498
src/components/pageCmp/cmp-modify.scss
Normal file
498
src/components/pageCmp/cmp-modify.scss
Normal file
@@ -0,0 +1,498 @@
|
||||
@import '../../assets/style/colors.scss'; // 修改门店基础信息
|
||||
|
||||
.cmp-modify-base {
|
||||
.modify-base-wrapper {
|
||||
height: calc(100vh - 1.8rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
.create-cell {
|
||||
font-size: 0.32rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.1rem 0.2rem;
|
||||
background: white;
|
||||
border-bottom: 1px solid $gray;
|
||||
min-height: 0.9rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 0.3rem;
|
||||
height: 0.3rem;
|
||||
fill: $sliver;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-text {
|
||||
width: 100%;
|
||||
color: $sliver;
|
||||
}
|
||||
|
||||
.cell-label {
|
||||
width: 2rem;
|
||||
color: $sliver;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cell-value {
|
||||
color: $black;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
.rangeInput {
|
||||
width: 100%;
|
||||
margin: 0 0.1rem;
|
||||
}
|
||||
.suffix {
|
||||
color: $sliver;
|
||||
}
|
||||
|
||||
.cell-input {
|
||||
flex: 1;
|
||||
color: $black;
|
||||
// border: 1px solid $danger;
|
||||
border: none;
|
||||
padding: 0.1rem;
|
||||
border-radius: 0.1rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.danger {
|
||||
border: 0.04rem dotted $danger;
|
||||
}
|
||||
|
||||
.cell-time1 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
color: $sliver;
|
||||
|
||||
.time {
|
||||
background: $lightGray;
|
||||
color: $black;
|
||||
padding: 0.1rem;
|
||||
border-radius: 0.1rem;
|
||||
width: 1.4rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-city {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
|
||||
.area {
|
||||
color: white;
|
||||
padding: 0.14rem 0.4rem;
|
||||
border-radius: 0.1rem;
|
||||
|
||||
&:nth-of-type(1) {
|
||||
background: $blue;
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
background: $success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.auto-open {
|
||||
justify-content: flex-start;
|
||||
.auto-open-text {
|
||||
color: $lightBlue;
|
||||
}
|
||||
.auto-open-button {
|
||||
background: $success;
|
||||
margin-left: .1rem;
|
||||
padding: 0.14rem 0.4rem;
|
||||
color: white;
|
||||
border-radius: .1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.printer-cell {
|
||||
justify-content: flex-start;
|
||||
.printer {
|
||||
// flex: 1;
|
||||
background: $success;
|
||||
margin-left: .1rem;
|
||||
padding: 0.14rem 0.4rem;
|
||||
color: white;
|
||||
border-radius: .1rem;
|
||||
}
|
||||
.test-print {
|
||||
margin-left: .4rem;
|
||||
color: $blue;
|
||||
// font-size: .28rem;
|
||||
border: 1px solid $blue;
|
||||
padding: 0.14rem 0.2rem;
|
||||
border-radius: .1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.header-title {
|
||||
font-size: 0.3rem;
|
||||
padding: 0.2rem 0.4rem;
|
||||
color: $lightBlack;
|
||||
border-bottom: 1px solid $gray;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
display: flex;
|
||||
margin-top: 0.5rem;
|
||||
box-shadow: 0 0 0.05rem $extraLightBlack;
|
||||
}
|
||||
|
||||
.delete-btn,
|
||||
.modify-btn {
|
||||
flex: 1;
|
||||
background: $blue;
|
||||
color: white;
|
||||
font-size: 0.32rem;
|
||||
height: 1rem;
|
||||
line-height: 1rem;
|
||||
text-align: center;
|
||||
// border-top: 1px solid $extraLightBlack;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
background: $danger;
|
||||
}
|
||||
}
|
||||
// 修改平台绑定
|
||||
|
||||
.cmp-modify-maps {
|
||||
.create-cell {
|
||||
font-size: 0.32rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.1rem 0.2rem;
|
||||
background: white;
|
||||
border-bottom: 1px solid $gray;
|
||||
min-height: 0.9rem;
|
||||
box-sizing: border-box;
|
||||
.cell-input {
|
||||
flex: 1;
|
||||
color: $black;
|
||||
// border: 1px solid $danger;
|
||||
border: none;
|
||||
padding: 0.1rem;
|
||||
border-radius: 0.1rem;
|
||||
outline: none;
|
||||
}
|
||||
.danger {
|
||||
border: 0.04rem dotted $danger;
|
||||
}
|
||||
.suffix-btn {
|
||||
color: white;
|
||||
background: $blue;
|
||||
height: .6rem;
|
||||
line-height: .6rem;
|
||||
padding: 0 .4rem;
|
||||
border-radius: .1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.suffix-text {
|
||||
color: $sliver;
|
||||
display: inline-block;
|
||||
width: 3rem;
|
||||
}
|
||||
.rangeInput {
|
||||
width: 100%;
|
||||
margin: 0 0.1rem;
|
||||
}
|
||||
.cell-text {
|
||||
width: 100%;
|
||||
color: $black;
|
||||
}
|
||||
.cell-vendorStoreID-text {
|
||||
color: $sliver;
|
||||
width: 100%;
|
||||
padding-left: .1rem;
|
||||
}
|
||||
.cell-label {
|
||||
width: 2rem;
|
||||
color: $sliver;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cell-value, .cell-value-checkbox {
|
||||
color: $black;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: center;
|
||||
|
||||
& > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.base-setting {
|
||||
margin: 0 .1rem;
|
||||
}
|
||||
}
|
||||
.cell-value-checkbox {
|
||||
padding-left: .1rem;
|
||||
}
|
||||
.no-bind {
|
||||
color: $extraLightBlack;
|
||||
}
|
||||
// 关店
|
||||
.status-0 {
|
||||
color: $danger;
|
||||
}
|
||||
// 开店
|
||||
.status-1 {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
.btn-insert, .btn-delete, .btn-update {
|
||||
flex-shrink: 0;
|
||||
background: #ccc;
|
||||
margin: 0 .1rem;
|
||||
width: .64rem;
|
||||
height: .64rem;
|
||||
display: flex;
|
||||
border-radius: .1rem;
|
||||
box-shadow: 0 0 .05rem $sliver;
|
||||
.svg {
|
||||
margin: auto;
|
||||
svg {
|
||||
width: .32rem;
|
||||
height: .32rem;
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-insert {
|
||||
background: $success;
|
||||
}
|
||||
.btn-delete {
|
||||
background: $danger;
|
||||
}
|
||||
.btn-update {
|
||||
background: $primary;
|
||||
}
|
||||
.success {
|
||||
color: $success;
|
||||
}
|
||||
.btn-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.orgCode {
|
||||
// flex: 1;
|
||||
color: $black;
|
||||
// border: 1px solid $danger;
|
||||
border: none;
|
||||
padding: 0.12rem;
|
||||
border-radius: 0.1rem;
|
||||
outline: none;
|
||||
background: $primary;
|
||||
width: 2rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 0.3rem;
|
||||
padding: 0.2rem 0.4rem;
|
||||
color: $lightBlack;
|
||||
border-bottom: 1px solid $gray;
|
||||
}
|
||||
}
|
||||
|
||||
// 分组管理
|
||||
.cmp-modify-group {
|
||||
.btn-group {
|
||||
display: flex;
|
||||
}
|
||||
.btn-addGroup, .btn-reg {
|
||||
flex: 1;
|
||||
font-size: .32rem;
|
||||
height: .9rem;
|
||||
line-height: .9rem;
|
||||
background: $primary;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
.btn-reg {
|
||||
background: $success;
|
||||
}
|
||||
.tel-input {
|
||||
width: 100%;
|
||||
font-size: .32rem;
|
||||
margin: .1rem 0;
|
||||
outline: none;
|
||||
border: 1px solid $sliver;
|
||||
padding: .1rem .2rem;
|
||||
box-sizing: border-box;
|
||||
border-radius: .1rem;
|
||||
}
|
||||
.tel-wrong {
|
||||
border-color: $danger;
|
||||
}
|
||||
.cell-input {
|
||||
// flex: 1;
|
||||
color: $black;
|
||||
border: 2px solid $success !important;
|
||||
border: none;
|
||||
padding: 0.1rem;
|
||||
border-radius: 0.1rem;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.danger {
|
||||
border: 2px dashed $danger !important;
|
||||
}
|
||||
// 组员卡片
|
||||
.card-wrapper {
|
||||
height: calc(100vh - 2.7rem);
|
||||
overflow: hidden;
|
||||
// overflow-y: auto;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
// padding: .4rem 0 ;
|
||||
// padding-bottom: 1rem;
|
||||
// padding: .2rem;
|
||||
& > div {
|
||||
padding: .2rem;
|
||||
}
|
||||
}
|
||||
.card {
|
||||
margin-bottom: .4rem;
|
||||
box-shadow: 0 1px 1px rgba(black, .2),
|
||||
0 8px 0 -3px white,
|
||||
0 9px 1px -3px rgba(black, .2),
|
||||
0 16px 0 -6px white,
|
||||
0 17px 2px -6px rgba(black, .2);
|
||||
border-radius: .1rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba($blue, .4);
|
||||
// border-bottom: none;
|
||||
}
|
||||
|
||||
.card-group, .card-group-member {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: .2rem;
|
||||
background: linear-gradient(to right, rgba($blue, .4), white);
|
||||
justify-content: space-between;
|
||||
.card-left {
|
||||
font-size: .32rem;
|
||||
color: $black;
|
||||
.tel {
|
||||
margin-top: .05rem;
|
||||
}
|
||||
.bind-id {
|
||||
display: flex;
|
||||
margin-top: .1rem;
|
||||
.no-bind {
|
||||
margin-right: .1rem;
|
||||
svg {
|
||||
width: .36rem;
|
||||
height: .36rem;
|
||||
fill: white;
|
||||
padding: .05rem;
|
||||
background: $gray;
|
||||
}
|
||||
}
|
||||
.is-bind {
|
||||
svg {
|
||||
background: $success;
|
||||
border-radius: .05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.card-right {
|
||||
margin-left: .2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.btn-editor, .btn-delete {
|
||||
width: .64rem;
|
||||
height: .64rem;
|
||||
border-radius: .1rem;
|
||||
box-shadow: 0 0 .05rem rgba($sliver, 1);
|
||||
box-sizing: border-box;
|
||||
border: .02rem solid white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.svg {
|
||||
font-size: .32rem;
|
||||
svg {
|
||||
width: .32rem;
|
||||
height: .32rem;
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-editor {
|
||||
background: $blue;
|
||||
}
|
||||
.btn-delete {
|
||||
margin-right: .1rem;
|
||||
background: $danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
.card-member-info {
|
||||
font-size: .28rem;
|
||||
background: white;
|
||||
text-align: center;
|
||||
height: .8rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
span {
|
||||
color: $lightSliver;
|
||||
margin-right: .2rem;
|
||||
}
|
||||
.btn-add-members {
|
||||
color: white;
|
||||
background: $success;
|
||||
padding: .14rem .2rem;
|
||||
border-radius: .1rem;
|
||||
}
|
||||
}
|
||||
.card-group-member {
|
||||
background: white;
|
||||
margin-bottom: 0;
|
||||
padding: .2rem .2rem .2rem .8rem;
|
||||
border-top: 1px solid rgba($blue, .4);
|
||||
.card-left {
|
||||
color: $extraLightBlack;
|
||||
font-size: .28rem;
|
||||
}
|
||||
}
|
||||
.no-thing {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
.no-store {
|
||||
svg {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
color: #ccc;
|
||||
font-size: .32rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
128
src/components/pageCmp/create-store.scss
Normal file
128
src/components/pageCmp/create-store.scss
Normal file
@@ -0,0 +1,128 @@
|
||||
// 创建门店
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
.create-store {
|
||||
padding-bottom: 1rem;
|
||||
.create-store-wrapper {
|
||||
height: calc(100vh - 1rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
.create-cell {
|
||||
font-size: .32rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: .1rem .2rem;
|
||||
background: white;
|
||||
border-bottom: 1px solid $gray;
|
||||
min-height: .9rem;
|
||||
box-sizing: border-box;
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
svg {
|
||||
width: .3rem;
|
||||
height: .3rem;
|
||||
fill: $sliver;
|
||||
}
|
||||
}
|
||||
.cell-label {
|
||||
width: 2rem;
|
||||
color: $sliver;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cell-value {
|
||||
color: $black;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
& > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
.cell-input {
|
||||
flex: 1;
|
||||
color: $black;
|
||||
// border: 1px solid $danger;
|
||||
border: none;
|
||||
padding: .1rem;
|
||||
border-radius: .1rem;
|
||||
outline: none;
|
||||
}
|
||||
.danger {
|
||||
border: .04rem dotted $danger;
|
||||
}
|
||||
.cell-time1 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
color: $sliver;
|
||||
.time {
|
||||
background: $lightGray;
|
||||
color: $black;
|
||||
padding: .1rem;
|
||||
border-radius: .1rem;
|
||||
width: 1.4rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.cell-city {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
.area {
|
||||
color: white;
|
||||
padding: .14rem .4rem;
|
||||
border-radius: .1rem;
|
||||
&:nth-of-type(1) {
|
||||
background: $blue;
|
||||
}
|
||||
&:nth-of-type(2) {
|
||||
background: $success;
|
||||
}
|
||||
}
|
||||
}
|
||||
.rangeInput {
|
||||
width: 100%;
|
||||
margin: 0 .1rem;
|
||||
}
|
||||
.suffix {
|
||||
color: $sliver;
|
||||
}
|
||||
}
|
||||
|
||||
.printer-cell {
|
||||
justify-content: flex-start;
|
||||
.printer {
|
||||
// flex: 1;
|
||||
background: $success;
|
||||
margin-left: .1rem;
|
||||
padding: 0.14rem 0.4rem;
|
||||
color: white;
|
||||
border-radius: .1rem;
|
||||
}
|
||||
}
|
||||
.has-suffix {
|
||||
.cell-input {
|
||||
// background: red;
|
||||
flex: 1;
|
||||
width: 2.6rem;
|
||||
}
|
||||
}
|
||||
.suffix2 {
|
||||
flex: 1;
|
||||
// flex-shrink: 0;
|
||||
// width: 4rem;
|
||||
font-size: .18rem;
|
||||
line-height: 1.5;
|
||||
color: $primary;
|
||||
}
|
||||
.header-title {
|
||||
font-size: .3rem;
|
||||
padding: .2rem .4rem;
|
||||
color: $lightBlack;
|
||||
border-bottom: 1px solid $gray;
|
||||
}
|
||||
}
|
||||
13
src/components/pageCmp/modify-store.scss
Normal file
13
src/components/pageCmp/modify-store.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
// 修改门店
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
// 基础信息修改
|
||||
.modify-store {
|
||||
.modify-wrapper {
|
||||
// margin-top: .05rem;
|
||||
height: calc(100vh - 1.8rem);
|
||||
// overflow-y: auto;
|
||||
overflow: hidden;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
40
src/components/pageCmp/more-search.scss
Normal file
40
src/components/pageCmp/more-search.scss
Normal file
@@ -0,0 +1,40 @@
|
||||
// 更多检索条件
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
.more-search {
|
||||
.search-cell {
|
||||
font-size: .32rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 .4rem;
|
||||
background: white;
|
||||
border-bottom: 1px solid $gray;
|
||||
min-height: 1rem;
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
svg {
|
||||
width: .3rem;
|
||||
height: .3rem;
|
||||
fill: $sliver;
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-cell + .search-cell {
|
||||
}
|
||||
.cell-label {
|
||||
width: 1.8rem;
|
||||
color: $sliver;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cell-value {
|
||||
color: $black;
|
||||
flex: 1;
|
||||
}
|
||||
.header-title {
|
||||
font-size: .3rem;
|
||||
padding: .2rem .4rem;
|
||||
color: $lightBlack;
|
||||
border-bottom: 1px solid $gray;
|
||||
}
|
||||
}
|
||||
49
src/components/pageCmp/store-cell.scss
Normal file
49
src/components/pageCmp/store-cell.scss
Normal file
@@ -0,0 +1,49 @@
|
||||
// 门店单元
|
||||
@import '../../assets/style/colors.scss';
|
||||
|
||||
.store-item {
|
||||
// padding: 0 .2rem;
|
||||
.store-cell {
|
||||
padding: .4rem .2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
// height: .6rem;
|
||||
align-items: center;
|
||||
background: white;
|
||||
line-height: 1;
|
||||
}
|
||||
.store-id {
|
||||
font-size: .28rem;
|
||||
color: $sliver;
|
||||
margin-right: .2rem;
|
||||
}
|
||||
.store-name {
|
||||
font-size: .32rem;
|
||||
color: $black;
|
||||
flex: 1;
|
||||
}
|
||||
.store-status {
|
||||
font-size: .24rem;
|
||||
padding: .08rem .12rem;
|
||||
border-radius: .3rem;
|
||||
color: white;
|
||||
margin-left: .2rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.status-jy {
|
||||
background: $danger;
|
||||
color: white;
|
||||
}
|
||||
.status-xx {
|
||||
background: $gray;
|
||||
}
|
||||
.status-yy {
|
||||
background: $success;
|
||||
color: white;
|
||||
}
|
||||
.city {
|
||||
font-size: .24rem;
|
||||
margin-left: .1rem;
|
||||
color: $sliver;
|
||||
}
|
||||
}
|
||||
109
src/components/zy-ui用法.txt
Normal file
109
src/components/zy-ui用法.txt
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
移动端组件使用方法
|
||||
*/
|
||||
|
||||
// ----- Dialog -----
|
||||
Dialog.show('标题', '内容', {
|
||||
showCancel: '是否显示取消按钮 默认是',
|
||||
cancelText: '取消按钮名称',
|
||||
confirmText: '确定按钮名称'
|
||||
}, res => {
|
||||
console.log(res); // true false
|
||||
});
|
||||
|
||||
// ----- Loading -----
|
||||
// 显示
|
||||
Loading.show();
|
||||
// 隐藏
|
||||
Loading.hide();
|
||||
|
||||
// ----- Toast -----
|
||||
|
||||
Toast.show('aaa', [timer = 5])
|
||||
|
||||
// ----- 弹出框PopupPage PopupPage2无动画-----
|
||||
title="更多检索条件"
|
||||
fnReturn={this.props.fnReturn.bind(this)}
|
||||
fnPrevConfirm={fn} ruturn true or false 确认前
|
||||
fnConfirm={this.props.fnConfirm.bind(this)}
|
||||
SVG
|
||||
|
||||
|
||||
// ----- 单选组件 -----
|
||||
/*
|
||||
fields={[
|
||||
{value: 0, text: '不限定'},
|
||||
{value: 1, text: '已绑定'},
|
||||
{value: -1, text: '未绑定'}
|
||||
]}
|
||||
id={} 对象名
|
||||
current={storeSearch.vendorStoreConds['0']}
|
||||
fnClick={} return val id
|
||||
*/
|
||||
|
||||
// ----- 多选组件 -----
|
||||
current={[]} [-1, 0, 1]
|
||||
fields={[
|
||||
{value: 1, text: '营业中'},
|
||||
{value: 0, text: '休息中'},
|
||||
{value: -1, text: '禁用中'}
|
||||
]}
|
||||
fnClick={this.changeStatuss.bind(this)} changeStatuss(val)
|
||||
|
||||
// ----- 自选组件CheckBoxSelf -----
|
||||
current={this.state.autoPickup}
|
||||
text="自动拣货"
|
||||
fields={[0, 1]} 假,真
|
||||
fnClick={this.changeStatuss.bind(this)} changeStatuss(val)
|
||||
|
||||
// ----- 列表 -----
|
||||
ref="checklist"
|
||||
datas={this.props.system.cityLevel2}
|
||||
map={{value: 'code', label: 'name'}}
|
||||
nullShow = false 是否显示空
|
||||
nullLabel = '' null显示
|
||||
current={storeSearch.placeID}
|
||||
title="城市选择"
|
||||
fnPick={this.cityPick.bind(this)}
|
||||
|
||||
this.refs.xxx.show()
|
||||
|
||||
// ----- 创建门店input -----
|
||||
|
||||
check={isNum} 校验函数
|
||||
value={this.state.id} 默认值
|
||||
placeholder=""
|
||||
errText="京西门店ID必须是纯数字" 报错提示
|
||||
fnBlur={this.idBlur.bind(this)} 失去焦点处理函数 可以为空
|
||||
|
||||
// ----- 地址选择组件 -----
|
||||
region 市名
|
||||
ref="SearchAddress"
|
||||
fnPick={this.fn.bind(this)}
|
||||
// 打开
|
||||
this.refs.xxx.show()
|
||||
|
||||
// ----- 选择输入框 -----
|
||||
pick input button
|
||||
|
||||
title="选择平台" // 选择面板标题
|
||||
placeholder="请输入平台门店ID"
|
||||
datas={[
|
||||
{id: 0, name: vendorName['0']},
|
||||
{id: 1, name: vendorName['1']},
|
||||
{id: 3, name: vendorName['3']}
|
||||
]}
|
||||
map={{value: 'id', label: 'name'}}
|
||||
current={this.state.vendorID} // 当前选择
|
||||
fnPick={this.handleVendorID} // 选择后处理函数,val
|
||||
fnChange={this.handleVendorStoreID} // 输入框改变处理函数,val
|
||||
fnConfirm={this.handleGetVendorStore} // 是否有确认按钮,且执行何种函数
|
||||
|
||||
// ----- 输入筛选 -----
|
||||
placeholder="请选择门店" fnPick={this.pickSrcStore}
|
||||
|
||||
// ----- 门店选择组件 -----
|
||||
ref="SearchAddress"
|
||||
fnPick={this.fn.bind(this)}
|
||||
// 打开
|
||||
this.refs.xxx.show()
|
||||
Reference in New Issue
Block a user