first commit
185
src/App.js
Normal file
@@ -0,0 +1,185 @@
|
||||
import React, { Component } from 'react';
|
||||
import {Route} from 'react-router-dom';
|
||||
import AnimatedRouter from 'react-animated-router'; //我们的AnimatedRouter组件
|
||||
import 'react-animated-router/animate.css'; //引入默认的动画样式定义
|
||||
import {connect} from 'react-redux';
|
||||
import {setToken, setCMS, setVendorOrgCode, setCityLevel2, setLogin} from '@/store/actions';
|
||||
import {DEBUG, temToken, debugPath} from '@/config';
|
||||
import fetchJson from '@/utils/fetch';
|
||||
import {setCookie, getCookie} from '@/utils/tools';
|
||||
import {mapPlaces} from '@/utils/mapData';
|
||||
// import * as dd from 'dingtalk-jsapi';
|
||||
import {getRoot} from '@/utils/getRoot.js'
|
||||
|
||||
// import HomePage from '@/pages/HomePage';
|
||||
import BottomBar from '@/components/BottomBar';
|
||||
import {IndexList, goodsManager, orderManager} from '@/router';
|
||||
import Other from '@/pages/Other';
|
||||
import DDAuth from '@/pages/DDAuth';
|
||||
import Loading from '@/components/Loading';
|
||||
import Register from '@/pages/Register';
|
||||
import KeepAlive, {AliveScope} from 'react-activation'
|
||||
import OrderManager from '@/pages/OrderManager';
|
||||
// import Dialog from '@/components/Dialog';
|
||||
|
||||
// 钉钉左侧按钮
|
||||
// if (dd.ios) {
|
||||
// dd.ready(() => {
|
||||
// dd.biz.navigation.setLeft({
|
||||
// control: true,
|
||||
// text: '关闭',
|
||||
// onSuccess: () => {
|
||||
// Dialog.show('提示', '是否离开【京西菜市管理平台】', {}, res => {
|
||||
// if (res) {
|
||||
// dd.biz.navigation.close();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
// } else if (dd.android) {
|
||||
// dd.ready(() => {
|
||||
// document.addEventListener('backbutton', function(e) {
|
||||
// e.preventDefault();
|
||||
// Dialog.show('提示', '是否离开【京西菜市管理平台】', {}, res => {
|
||||
// if (res) {
|
||||
// dd.biz.navigation.close();
|
||||
// }
|
||||
// });
|
||||
// return false;
|
||||
// // window.location.href =src;
|
||||
// });
|
||||
// })
|
||||
// }
|
||||
|
||||
// 关闭手机滑动
|
||||
document.querySelector('body').addEventListener('touchmove', e => {
|
||||
e.preventDefault();
|
||||
}, {passive: false});
|
||||
|
||||
class App extends Component {
|
||||
// constructor (...args) {
|
||||
// super(...args);
|
||||
// }
|
||||
// async componentDidUpdate () {
|
||||
// console.log('app did update');
|
||||
// // await this.checkLogin();
|
||||
// }
|
||||
async componentDidMount () {
|
||||
// 获取权限信息
|
||||
console.log('获取权限')
|
||||
await getRoot()
|
||||
await this.checkLogin();
|
||||
}
|
||||
// 检测登录信息
|
||||
async checkLogin () {
|
||||
setCookie('token', '')
|
||||
if (!this.props.user.login && this.props.location.pathname !== '/ddauth') {
|
||||
if (DEBUG) {
|
||||
// 调试模式
|
||||
console.log('Debug')
|
||||
await this.props.setToken(temToken);
|
||||
await setCookie('token', temToken);
|
||||
await this.props.setLogin(true);
|
||||
await this.getBase();
|
||||
// this.props.history.push('/orderdetail?vendorOrderID=916837487000241');
|
||||
// this.props.history.push('/wmtojx');
|
||||
this.props.history.push(debugPath);
|
||||
} else {
|
||||
// 正式环境
|
||||
// 查看cookie是否存在
|
||||
let token = getCookie('token');
|
||||
console.log(token);
|
||||
if (!token) {
|
||||
console.log('token 不存在');
|
||||
this.props.history.push('/ddauth');
|
||||
return false;
|
||||
} else {
|
||||
// 存在token
|
||||
console.log('App.js:存在token')
|
||||
await this.props.setToken(token, 7);
|
||||
await this.props.setLogin(true);
|
||||
await this.getBase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 请求基础信息
|
||||
async getBase () {
|
||||
try {
|
||||
Loading.show();
|
||||
// 请求
|
||||
let {metaData} = await fetchJson('/v2/cms/GetServiceInfo');
|
||||
// 请求城市列表 level = 2
|
||||
let res = await fetchJson('/v2/cms/GetPlaces?level=2');
|
||||
// 请求平台账号
|
||||
let vendorOrgCode = await fetchJson('/v2/cms/GetVendorOrgCodeInfo')
|
||||
// let vendorOrgCode = {"0":["320406","349454"],"1":["589"],"3":["34665"]}
|
||||
// console.log(metaData);
|
||||
// DEBUG
|
||||
// if (DEBUG) vendorOrgCode['0'][1] = '123456'
|
||||
console.log('平台账号', vendorOrgCode)
|
||||
this.props.setCMS(metaData);
|
||||
this.props.setCityLevel2(mapPlaces(res));
|
||||
this.props.setVendorOrgCode(vendorOrgCode)
|
||||
console.log('Places', mapPlaces(res));
|
||||
console.log('CMS', this.props.system.cms);
|
||||
} catch (e) {} finally {
|
||||
Loading.hide();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
// 是否显示底部菜单
|
||||
let bottomShow = IndexList.some(item => item.to === this.props.location.pathname)
|
||||
return (
|
||||
<div className="App">
|
||||
{
|
||||
this.props.user.login && (
|
||||
<div>
|
||||
<AnimatedRouter>
|
||||
{
|
||||
IndexList.map((link, index) => (
|
||||
link.text !== '订单管理' ? <Route key={index} path={link.to} component={link.component} exact></Route> : <AliveScope key={index}>
|
||||
<Route path={link.to} exact render={
|
||||
props => (
|
||||
<KeepAlive>
|
||||
<OrderManager {...props}></OrderManager>
|
||||
</KeepAlive>
|
||||
)
|
||||
}></Route>
|
||||
</AliveScope>
|
||||
))
|
||||
}
|
||||
</AnimatedRouter>
|
||||
<Route path="/other" exact component={Other}></Route>
|
||||
{/* 商品管理子页面 */}
|
||||
{
|
||||
goodsManager.map((link, index) => (
|
||||
<Route path={link.to} component={link.component} key={index}></Route>
|
||||
))
|
||||
}
|
||||
{/* 订单管理子页面 */}
|
||||
{
|
||||
orderManager.map((link, index) => (
|
||||
<Route path={link.to} component={link.component} key={index}></Route>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* 钉钉auth */}
|
||||
<Route path="/ddauth" exact component={DDAuth}></Route>
|
||||
<Route path="/register" exact component={Register}></Route>
|
||||
|
||||
{/* 底部菜单 */}
|
||||
{
|
||||
bottomShow && <BottomBar></BottomBar>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect((state, props) => Object.assign({}, props, state), {
|
||||
setToken, setCMS, setCityLevel2, setLogin, setVendorOrgCode
|
||||
})(App);
|
||||
195
src/apis/store.txt
Normal file
@@ -0,0 +1,195 @@
|
||||
get /store/GetStores 获取门店信息
|
||||
*token
|
||||
keyword str 关键字
|
||||
storeID int 门店ID
|
||||
name str 门店名称(模糊)
|
||||
placeID int 所属地点ID
|
||||
placeLevel int 所属地点级别
|
||||
address str 门店地址
|
||||
tel str 电话
|
||||
statuss str [-1, 0, 1] -1禁用 0休息 1正常
|
||||
vendorStoreCond str 查询平台门店绑定条件 and与 or或
|
||||
vendorStoreConds str {vendorID: cond} cond: -1没有关联 0不限定 1有关联
|
||||
courierStoreCond str 查询专送门店绑定条件 and与 or或
|
||||
courierStoreConds
|
||||
offset int 起始序号
|
||||
pageSize int 页码大小
|
||||
|
||||
{
|
||||
"id": 101914,
|
||||
"createdAt": "2019-02-25T15:07:33+08:00",
|
||||
"updatedAt": "2019-02-25T15:07:33+08:00",
|
||||
"lastOperator": "zhaominfu",
|
||||
"deletedAt": "1970-01-01T00:00:00+08:00",
|
||||
"name": "成华悦都农贸店",
|
||||
"cityCode": 510100,
|
||||
"districtCode": 510108,
|
||||
"address": "成华区桃竹路55号一楼44、45号",
|
||||
"tel1": "15088537275",
|
||||
"tel2": "",
|
||||
"openTime1": 730,
|
||||
"closeTime1": 1800,
|
||||
"openTime2": 0,
|
||||
"closeTime2": 0,
|
||||
"deliveryRangeType": 2,
|
||||
"deliveryRange": "104.106488,30.680477;104.109639,30.682390;104.108228,30.685010;104.111904,30.687921;104.116220,30.684203;104.118888,30.686362;104.123694,30.682666;104.121355,30.680289;104.121605,30.679253;104.108628,30.675569;104.106502,30.679381;104.106488,30.680477",
|
||||
"status": -1,
|
||||
"changePriceType": 0,
|
||||
"idCardFront": "",
|
||||
"idCardBack": "",
|
||||
"idCardHand": "",
|
||||
"licence": "",
|
||||
"licenceCode": "",
|
||||
"lng": 104.116913,
|
||||
"lat": 30.680007,
|
||||
"cityName": "成都市",
|
||||
"districtName": "成华区",
|
||||
"StoreMaps": [
|
||||
{
|
||||
"status": 1,
|
||||
"vendorID": 0,
|
||||
"vendorStoreID": "11850802"
|
||||
}
|
||||
],
|
||||
"CourierMaps": [
|
||||
{
|
||||
"status": 1,
|
||||
"vendorID": 101,
|
||||
"vendorStoreID": "101914"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// 创建门店
|
||||
post /store/CreateStore
|
||||
token
|
||||
payload
|
||||
|
||||
// 修改门店
|
||||
put /store/UpdateStore formData
|
||||
token
|
||||
storeID
|
||||
payload
|
||||
|
||||
// 获取平台门店
|
||||
get /store/GetStoreVendorMaps
|
||||
storeID
|
||||
vendorID 默认全部
|
||||
|
||||
// 获取转送门店
|
||||
get /store/GetStoreCourierMaps
|
||||
storeID
|
||||
vendorID 默认全部
|
||||
|
||||
// 查询平台门店
|
||||
get /store/GetVendorStore
|
||||
vendorStoreID
|
||||
vendorID
|
||||
|
||||
// 绑定平台门店
|
||||
post /store/AddStoreVendorMap
|
||||
storeID
|
||||
vendorID
|
||||
payload
|
||||
|
||||
// 绑定专送门店
|
||||
post /store/AddStoreCourierMap
|
||||
storeID
|
||||
vendorID
|
||||
payload status, vendorStoreId
|
||||
|
||||
创建门店json
|
||||
{
|
||||
"id": 0,
|
||||
"createdAt": "0001-01-01T00:00:00Z",
|
||||
"updatedAt": "0001-01-01T00:00:00Z",
|
||||
"lastOperator": "",
|
||||
"deletedAt": "0001-01-01T00:00:00Z",
|
||||
"name": "成华悦都农贸店2",
|
||||
"cityCode": 510100,
|
||||
"districtCode": 510108,
|
||||
"address": "成华区桃竹路55号一楼44、45号",
|
||||
"tel1": "15088537275",
|
||||
"tel2": "",
|
||||
"openTime1": 730,
|
||||
"closeTime1": 1800,
|
||||
"openTime2": 0,
|
||||
"closeTime2": 0,
|
||||
"deliveryRangeType": 3, 半径 2规划范围
|
||||
"deliveryRange": "3000",
|
||||
"status": 1,
|
||||
"changePriceType": 0,
|
||||
"idCardFront": "",
|
||||
"idCardBack": "",
|
||||
"idCardHand": "",
|
||||
"licence": "",
|
||||
"licenceCode": "",
|
||||
"deliveryType": 0,
|
||||
"lng": 104.116913,
|
||||
"lat": 30.680007,
|
||||
"cityName": "成都市",
|
||||
"districtName": "成华区",
|
||||
"StoreMaps": null,
|
||||
"CourierMaps": null,
|
||||
"getVendorStore": "11850802"
|
||||
}
|
||||
|
||||
绑定 payload
|
||||
|
||||
{
|
||||
"vendorStoreID":"11850802",
|
||||
"status":1,
|
||||
"vendorID":0,
|
||||
"autoPickup":1,
|
||||
"deliveryCompetition":1,
|
||||
"pricePercentage":100,
|
||||
"isSync":1
|
||||
}
|
||||
|
||||
|
||||
编辑门店映射 put /store/UpdateStoreVendorMap
|
||||
storeID int query
|
||||
vendorID
|
||||
payload
|
||||
获取的数据
|
||||
|
||||
autoPickup: 1
|
||||
deliveryCompetition: 1
|
||||
deliveryType: 0
|
||||
isSync: 1
|
||||
pricePercentage: 100
|
||||
status: 1
|
||||
storeID: 101912
|
||||
syncStatus: 0
|
||||
vendorID: 0
|
||||
vendorStoreID: "11733019"
|
||||
|
||||
删除门店映射 delete /store/DeleteStoreVendorMap
|
||||
storeID
|
||||
vendorID
|
||||
|
||||
-----------------------------
|
||||
得到专送门店绑定信息 get /store/GetStoreCourierMaps
|
||||
storeID
|
||||
vendorID
|
||||
|
||||
{
|
||||
storeID: 100118,
|
||||
vendorID: 102,
|
||||
vendorStoreID: 123123,
|
||||
status: 1
|
||||
}
|
||||
|
||||
修改专送门店 put /store/UpdateStoreCourierMap formdata
|
||||
storeID
|
||||
vendorID
|
||||
payload
|
||||
|
||||
新增专送门店 post /store/AddStoreCourierMap formdata
|
||||
storeID
|
||||
vendorID
|
||||
payload
|
||||
|
||||
删除专送门店 delete /store/DeleteStoreCourierMap query
|
||||
storeID
|
||||
vendorID
|
||||
29
src/apis/tool.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
// 京西门店复制到京西门店
|
||||
post /store/sku/CopyStoreSkus formData
|
||||
fromStoreID
|
||||
toStoreID
|
||||
copyMode fresh全部清除后复制 update只复制指定商品
|
||||
pricePercentage
|
||||
skuIDs: []
|
||||
|
||||
// 同步到平台
|
||||
put /store/sku/SyncStoresSkus formData
|
||||
storeIDs []
|
||||
vendorIDs: []
|
||||
isAsync boo
|
||||
isContinueWhenError 单个失败继续
|
||||
skuIDs: []
|
||||
|
||||
// 初始化商品
|
||||
put /sync/FullSyncStoresSkus formData
|
||||
storeIDs
|
||||
vendorIDs
|
||||
isAsync
|
||||
isContinueWhenError
|
||||
|
||||
// 删除远程门店
|
||||
delete /sync/DeleteRemoteStoreSkus
|
||||
storeIDs
|
||||
vendorIDs
|
||||
isAsync
|
||||
isContinueWhenError
|
||||
50
src/apis/user.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
get /user/TmpGetStoreUsers
|
||||
storeID
|
||||
|
||||
// 数据
|
||||
createdAt: "0001-01-01T00:00:00Z"
|
||||
id: 671
|
||||
lastOperator: ""
|
||||
members: null
|
||||
nickname: "null"
|
||||
openID: "oYN_usu4RYlLR4QcfXGpkhwrqgLI"
|
||||
openIDMini: ""
|
||||
openIDUnion: ""
|
||||
parentID: -1
|
||||
parentMobile: ""
|
||||
storeID: 100118
|
||||
tel: "18583789973"
|
||||
updatedAt: "0001-01-01T00:00:00Z"
|
||||
|
||||
members
|
||||
|
||||
createdAt: "0001-01-01T00:00:00Z"
|
||||
id: 18763
|
||||
lastOperator: ""
|
||||
nickname: "周小扬"
|
||||
openID: ""
|
||||
openIDMini: ""
|
||||
openIDUnion: ""
|
||||
parentID: 671
|
||||
storeID: 0
|
||||
tel: "13684045763"
|
||||
updatedAt: "0001-01-01T00:00:00Z"
|
||||
|
||||
解绑
|
||||
PUT /user/TmpUnbindMobile
|
||||
mobile
|
||||
|
||||
绑定分组
|
||||
PUT /user/TmpBindMobile2Store
|
||||
mobile
|
||||
storeID
|
||||
|
||||
绑定组员
|
||||
PUT /user/TmpAddMobile2Mobile
|
||||
parentMobile
|
||||
mobile
|
||||
|
||||
修改号码
|
||||
PUT /user/TmpChangeMobile
|
||||
curMobile 当前
|
||||
expectedMobile 新
|
||||
81
src/apis/登录接口.txt
Normal file
@@ -0,0 +1,81 @@
|
||||
钉钉扫码
|
||||
https://oapi.dingtalk.com/connect/qrconnect?appid=dingoashf4onhetkegzh3i&response_type=code&scope=snsapi_login&state=&redirect_uri=http://www.jxc4.com/beta/v2/auth2/DingDingOAuth2
|
||||
|
||||
微信公众号认证回调接口
|
||||
/auth2/WeixinMPOAuth2 get
|
||||
*code str 客户同意后得到的code
|
||||
*block str 回调地址
|
||||
state str 微信回调的登录状态
|
||||
----得到的数据
|
||||
type 从哪登录
|
||||
TokenType 1是有用户信息,2是没有用户信息
|
||||
|
||||
user2
|
||||
用户注册
|
||||
/user2/RegisterUser post(formData)
|
||||
*payload json数据,User对象(手机号必填)
|
||||
*mobileVerifyCode 手机验证码(通过auth2.SendVerifyCode获得)
|
||||
authToken 之前通过login得到的认证TOKEN(可以为空)
|
||||
|
||||
----payload
|
||||
UserID2 str 用户名(英文数字下划线)
|
||||
Name str 昵称
|
||||
Mobile str 手机号
|
||||
Email string `orm:"size(32)" json:"email"`
|
||||
IDCardNo string `orm:"size(18);column(id_card_no)" json:"idCardNo"` // 身份证号
|
||||
|
||||
发送验证码
|
||||
/auth2/SendVerifyCode post
|
||||
*captchaID str 图片验证码ID
|
||||
*captchaValue str 图片验证码值
|
||||
authToken str 之前的认证token
|
||||
*authID str 手机号或邮件
|
||||
|
||||
登录接口
|
||||
/auth2/Login post(formData)
|
||||
*authType str localpass:本地账号密码
|
||||
mobile:手机短信
|
||||
weixin:微信登录--扫码登录
|
||||
weixinsns:微信公众号登录
|
||||
weixinmini:小程序登录
|
||||
ddstaff: 钉钉
|
||||
*authSecret str 登录密码, localpass(md5)
|
||||
authID str 对应type值
|
||||
authIDType str localpass时才有意义,分别为 userid2:用户名,email,mobild
|
||||
|
||||
auth2
|
||||
绑定认证方式
|
||||
/auth2/AddAuthBind post(formData)
|
||||
*token 认证token
|
||||
authToken 之前通过login得到的新认证TOKEN(临时token)
|
||||
|
||||
修改密码
|
||||
/auth2/ChangePassword put
|
||||
*token
|
||||
oldPwd 原密码md5,如果是重置或新设,为空
|
||||
newPwd 新密码md5
|
||||
|
||||
生成校验图
|
||||
/auth2/CreateCaptcha post(formData)
|
||||
*width int 图片宽
|
||||
*height int 图片高
|
||||
captchaLen 验证码长度(默认4)
|
||||
|
||||
登出接口
|
||||
/auth2/Logout delete
|
||||
*token
|
||||
|
||||
解绑认证方式
|
||||
/auth2/RemoveAuthBind post
|
||||
*token
|
||||
authType str weixin:微信登录,weixinsns:微信公众号登录,weixinmini;小程序登录
|
||||
|
||||
微信认证回调接口-扫码登录
|
||||
/auth2/WeixinOAuth2 get
|
||||
*code str 客户同意后得到的code
|
||||
*block str 回调地址
|
||||
state str 微信回调的登录状态
|
||||
|
||||
得到用户已经成功绑定的认证信息
|
||||
/user2/GetBindAuthInfo get
|
||||
token 认证token
|
||||
BIN
src/assets/imgs/dd-bind.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
src/assets/imgs/ic_eb.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/assets/imgs/ic_jd.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/assets/imgs/ic_jx.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/assets/imgs/ic_mt.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
src/assets/imgs/icon-clear.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/imgs/icon-code.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/imgs/icon-nickname.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/imgs/icon-nickname2.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/imgs/icon-tel.png
Normal file
|
After Width: | Height: | Size: 525 B |
BIN
src/assets/imgs/icon-username.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/imgs/loading.gif
Normal file
|
After Width: | Height: | Size: 77 KiB |
32
src/assets/style/_colors.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
element 配色风格
|
||||
*/
|
||||
|
||||
// 主色
|
||||
$lightBlue: #58B7FF;
|
||||
$blue: #20A0FF;
|
||||
$darkBlue: #1D8CE0;
|
||||
|
||||
// 辅助色
|
||||
$primary: #20A0FF;
|
||||
$success: #13CE66;
|
||||
$warning: #F7BA2A;
|
||||
$danger: #FF4949;
|
||||
|
||||
// 中性色
|
||||
$black: #1F2D3D;
|
||||
$lightBlack: #324057;
|
||||
$extraLightBlack: #475669;
|
||||
|
||||
$sliver: #8492A6;
|
||||
$lightSliver: #99A9BF;
|
||||
$extraLightSliver: #C0CCDA;
|
||||
|
||||
$gray: #D3DCE6;
|
||||
$lightGray: #E5E9F2;
|
||||
$extraLightGray: #EFF2F7;
|
||||
|
||||
$darkWhite: #F9FAFC;
|
||||
$white: #FFFFFF;
|
||||
|
||||
$maskColor: rgba(black, .6);
|
||||
11
src/assets/style/_icon.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
%icon-store {
|
||||
background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cpath d='M950.635 366.916c0-3.869-1.937-5.802-1.937-5.802l-75.446-187.648c-13.542-38.69-50.296-61.905-94.79-61.905h-526.18c-44.494 0-79.312 23.213-92.853 59.968L78.181 363.046c0 1.932 0 1.932-1.938 3.869-5.803 17.41-9.672 36.754-9.672 54.165 0 65.77 36.755 125.742 92.858 154.757 23.213 13.542 52.228 19.35 83.181 19.35 52.234 0 100.597-23.219 135.413-63.844 32.89 38.692 81.25 61.905 133.481 61.905 52.234 0 100.592-23.212 133.482-61.905 32.885 38.692 81.25 61.905 135.415 61.905 32.884 0 59.967-7.738 85.117-19.343 56.098-30.951 92.853-90.919 92.853-154.762 1.935-15.472-1.933-34.815-7.736-52.227zm-114.14 152.826c-15.472 7.74-32.883 11.604-54.165 11.604-38.686 0-75.446-19.343-94.79-54.165-1.931-3.87-3.868-7.734-7.738-13.541-5.803-5.802-15.474-13.543-30.948-13.543-13.54 0-25.149 5.807-30.951 13.543-3.87 5.807-5.807 9.671-7.74 13.541-21.28 32.89-56.103 54.165-94.789 54.165-38.691 0-73.513-19.343-94.79-54.165-1.935-3.87-3.87-7.734-7.74-11.603-15.473-17.412-48.363-17.412-61.903-1.937-5.802 5.807-7.735 9.671-9.673 13.542-21.28 32.889-56.098 52.232-94.79 54.164-21.28 0-38.69-3.864-52.233-11.604-36.754-19.344-59.967-58.035-59.967-98.66 0-11.607 1.931-25.15 5.802-36.754v-1.937l79.316-187.64c1.931-3.871 5.803-19.349 30.952-19.349h528.114c9.676 0 27.082 1.936 34.821 21.28l75.447 185.71v3.87c3.869 11.609 5.8 25.15 5.8 36.754.002 40.623-21.278 77.381-58.034 96.725zm25.152 104.461c-17.41 0-32.883 13.542-32.883 32.884v174.105a17.34 17.34 0 0 1-17.412 17.412H207.788a17.336 17.336 0 0 1-17.408-17.412V659.024c0-17.41-13.54-32.89-32.889-32.89-17.41 0-32.884 13.542-32.884 32.89v172.168c0 44.495 36.754 81.249 81.248 81.249h603.56c44.495 0 81.248-36.754 81.248-83.181V655.155c1.936-17.41-11.604-30.952-29.016-30.952zM764.921 397.87H252.28c-17.411 0-32.885-13.542-32.885-32.89 0-17.407 13.54-32.885 32.884-32.885h512.64c17.41 0 32.889 13.541 32.889 32.884.001 19.349-15.478 32.89-32.888 32.89z' fill='%2320A0FF'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
%icon-search {
|
||||
background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cpath d='M771.235 696.266l237.244 237.245a52.979 52.979 0 0 1-74.913 74.913l-237.299-237.19a431.158 431.158 0 1 1 74.914-74.914zm-340.076 58.26a323.368 323.368 0 1 0 0-646.737 323.368 323.368 0 0 0 0 646.737z' fill='%23D3DCE6'/%3E%3C/svg%3E")
|
||||
}
|
||||
|
||||
%icon-clear {
|
||||
background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cpath d='M511.3 42.6c-259 0-469 210-469 469s210 469 469 469 469-210 469-469-209.9-469-469-469zm219.2 618.5c19.4 19.4 19.4 51.3 0 70.7-19.4 19.4-51.3 19.4-70.7 0l-149-149-148 148c-19.4 19.4-51.3 19.4-70.7 0-19.4-19.4-19.4-51.3 0-70.7l148-148-148-148c-19.4-19.4-19.4-51.3 0-70.7 19.4-19.4 51.3-19.4 70.7 0l148 148 149-149c19.4-19.4 51.3-19.4 70.7 0 19.4 19.4 19.4 51.3 0 70.7l-149 149 149 149z' fill='%23D3DCE6'/%3E%3C/svg%3E")
|
||||
}
|
||||
110
src/assets/style/_store-manager.scss
Normal file
@@ -0,0 +1,110 @@
|
||||
// 门店管理
|
||||
.storeManager {
|
||||
// 检索框
|
||||
.search {
|
||||
background: $blue;
|
||||
height: 1rem;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
padding: 0 .2rem;
|
||||
justify-content: space-between;
|
||||
// position: fixed;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// z-index: 100;
|
||||
.input-group {
|
||||
flex: 1;
|
||||
// height: 100%;
|
||||
font-size: 0;
|
||||
display: flex;
|
||||
position: relative;
|
||||
input {
|
||||
margin: auto;
|
||||
font-size: .28rem;
|
||||
width: 100%;
|
||||
height: .6rem;
|
||||
border-radius: .6rem;
|
||||
border: 1px solid $gray;
|
||||
box-sizing: border-box;
|
||||
padding-left: .6rem;
|
||||
padding-right: .8rem;
|
||||
color: $black;
|
||||
outline: none;
|
||||
font-family: "Microsoft Yahei";
|
||||
}
|
||||
.icon-search {
|
||||
position: absolute;
|
||||
left: .14rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
// width: .3rem;
|
||||
// height: .3rem;
|
||||
svg {
|
||||
fill: $gray;
|
||||
width: .32rem;
|
||||
height: .32rem;
|
||||
}
|
||||
}
|
||||
.icon-clear {
|
||||
position: absolute;
|
||||
right:0;
|
||||
// background: rgba(black, .4);
|
||||
// height: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
padding: .2rem .2rem;
|
||||
svg {
|
||||
fill: $gray;
|
||||
width: .32rem;
|
||||
height: .32rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-create, .btn-more {
|
||||
background: $white;
|
||||
font-size: .24rem;
|
||||
border-radius: 50%;
|
||||
width: .6rem;
|
||||
height: .6rem;
|
||||
line-height: .6rem;
|
||||
text-align: center;
|
||||
color: $blue;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
.icon {
|
||||
margin: auto;
|
||||
svg {
|
||||
fill: $blue;
|
||||
width: .3rem;
|
||||
height: .3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-create {}
|
||||
.btn-more {
|
||||
margin: 0 .2rem;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
// padding-top: 1rem;
|
||||
}
|
||||
.store-item + .store-item {
|
||||
border-top: 2px solid $gray;
|
||||
}
|
||||
.no-thing {
|
||||
text-align: center;
|
||||
margin-top: 2rem;
|
||||
.no-store {
|
||||
svg {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
color: #ccc;
|
||||
font-size: .32rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
98
src/assets/style/ddauth.scss
Normal file
@@ -0,0 +1,98 @@
|
||||
$maincolor: #409EFF;
|
||||
@keyframes bannerIn {
|
||||
from {
|
||||
transform: translate(-50%, -100%);
|
||||
opacity: .5;
|
||||
}
|
||||
to {
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes btnIn {
|
||||
from {
|
||||
transform: translate(-50%, 100%);
|
||||
opacity: .5;
|
||||
}
|
||||
to {
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 授权登录
|
||||
.auth {
|
||||
background: #fafafa;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
.banner {
|
||||
position: fixed;
|
||||
width: 3.32rem;
|
||||
height: 1.12rem;
|
||||
left: 50%;
|
||||
top: 30%;
|
||||
transform: translate(-50%, 0);
|
||||
transform-origin: center center;
|
||||
background: url(../imgs/dd-bind.png) center center no-repeat;
|
||||
background-size: 100%;
|
||||
animation: bannerIn 1s ease-in-out;
|
||||
}
|
||||
.btn-getcode {
|
||||
font-size: .36rem;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 56%;
|
||||
transform: translate(-50%, 0);
|
||||
text-align: center;
|
||||
background: #409EFF;
|
||||
color: white;
|
||||
padding: .2rem .6rem;
|
||||
border-radius: .2rem;
|
||||
box-shadow: 0 .05rem .1rem rgba(#ccc, .8), 0 .03rem .1rem rgba(#ccc, .8),0 0 .1rem rgba(#ccc, .8);
|
||||
border: 2px solid white;
|
||||
width: 3rem;
|
||||
animation: btnIn 1s ease-in-out;
|
||||
}
|
||||
.bottom-text {
|
||||
font-size: .2rem;
|
||||
position: fixed;
|
||||
bottom: .4rem;
|
||||
color: #999;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新用户
|
||||
.register {
|
||||
background: #fafafa;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
// padding: .2rem;
|
||||
box-sizing: border-box;
|
||||
.form-wrapper {
|
||||
padding: 0 .2rem;
|
||||
background: white;
|
||||
box-shadow: 0 1px .05rem 0 rgba(0,0,0,.05);
|
||||
}
|
||||
h2 {
|
||||
color: $maincolor;
|
||||
font-size: .4rem;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: .5rem 0 .2rem 0;
|
||||
}
|
||||
.btn-register {
|
||||
width: 6.8rem;
|
||||
margin: 1rem auto 0;
|
||||
height: .94rem;
|
||||
color: white;
|
||||
border-radius: .1rem;
|
||||
border: 2px solid rgba($maincolor,.8);
|
||||
background: $maincolor;
|
||||
font-size: .36rem;
|
||||
text-align: center;
|
||||
line-height: .94rem;
|
||||
}
|
||||
}
|
||||
53
src/assets/style/global.scss
Normal file
@@ -0,0 +1,53 @@
|
||||
@import './colors.scss';
|
||||
@import './store-manager.scss';
|
||||
|
||||
* {
|
||||
line-height: 1;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
|
||||
}
|
||||
|
||||
.height100vh-100px {
|
||||
height: calc(100vh - 1rem);
|
||||
overflow-y: auto;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.height100vh-180px {
|
||||
height: calc(100vh - 1.8rem);
|
||||
overflow-y: auto;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
background: #fafafa;
|
||||
}
|
||||
.height100vh-200px {
|
||||
height: calc(100vh - 2rem);
|
||||
overflow: hidden;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
background: #fafafa;
|
||||
}
|
||||
.padding-bottom-1rem {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.pointerNone {
|
||||
pointer-events: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.pointerAll {
|
||||
pointer-events: all;
|
||||
touch-action: auto;
|
||||
}
|
||||
|
||||
.code105 {
|
||||
height: 60vh;
|
||||
overflow: hidden;
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid $gray;
|
||||
color: $primary;
|
||||
span {
|
||||
color: $sliver;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/assets/style/goods-manager.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
@import './colors.scss';
|
||||
// 门店管理
|
||||
.goods-manager {
|
||||
.header-title {
|
||||
height: 1rem;
|
||||
background: $blue;
|
||||
font-size: .32rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
line-height: 1rem;
|
||||
}
|
||||
.link-cell {
|
||||
display: flex;
|
||||
font-size: .32rem;
|
||||
height: 1rem;
|
||||
background: white;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 .2rem;
|
||||
text-decoration: none;
|
||||
color: $black;
|
||||
.icon {
|
||||
svg {
|
||||
width: .4rem;
|
||||
height: .4rem;
|
||||
fill: $lightSliver;
|
||||
}
|
||||
}
|
||||
}
|
||||
.link-cell + .link-cell {
|
||||
border-top: 1px solid $gray;
|
||||
}
|
||||
}
|
||||
138
src/assets/style/order-manager.scss
Normal file
@@ -0,0 +1,138 @@
|
||||
@import './colors.scss';
|
||||
@import './icon.scss';
|
||||
// 订单管理样式
|
||||
.order-manager {
|
||||
font-size: .32rem;
|
||||
.search {
|
||||
height: 1rem;
|
||||
box-sizing: border-box;
|
||||
padding: .2rem;
|
||||
background: $blue;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon-store, .icon-search, .icon-clear {
|
||||
flex: none;
|
||||
width: .6rem;
|
||||
height: .6rem;
|
||||
@extend %icon-store;
|
||||
background-size: .36rem;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.icon-search {
|
||||
@extend %icon-search;
|
||||
background-size: .32rem;
|
||||
}
|
||||
.icon-clear {
|
||||
@extend %icon-clear;
|
||||
}
|
||||
input {
|
||||
flex: 1;
|
||||
font-size: .28rem;
|
||||
color: $black;
|
||||
outline: none;
|
||||
font-family: "Microsoft Yahei";
|
||||
border: none;
|
||||
margin-right: .1rem;
|
||||
}
|
||||
.input-group {
|
||||
margin-left: .2rem;
|
||||
flex: 1;
|
||||
background: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: .6rem;
|
||||
border-radius: .3rem;
|
||||
border: 1px solid $gray;
|
||||
}
|
||||
}
|
||||
.wrapper {
|
||||
height: calc(100vh - 2rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
.content {
|
||||
font-size: .3rem;
|
||||
}
|
||||
.item {
|
||||
text-align: center;
|
||||
padding: .5rem 0;
|
||||
color: white;
|
||||
background: #ccc;
|
||||
}
|
||||
.order-list {
|
||||
padding: .2rem;
|
||||
color: $black;
|
||||
border-bottom: 1px solid $gray;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: .8rem;
|
||||
& > * {
|
||||
flex: none;
|
||||
}
|
||||
.order-created {
|
||||
font-size: .24rem;
|
||||
margin-left: .1rem;
|
||||
}
|
||||
.vendorID {
|
||||
border-radius: .1rem;
|
||||
border: 1px solid $gray;
|
||||
width: .4rem;
|
||||
height: .4rem;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
.vendor-icon-0 {
|
||||
background-image: url(../imgs/ic_jd.png);
|
||||
}
|
||||
.vendor-icon-1 {
|
||||
background-image: url(../imgs/ic_mt.png);
|
||||
}
|
||||
.vendor-icon-3 {
|
||||
background-image: url(../imgs/ic_eb.png);
|
||||
}
|
||||
.vendor-icon-9 {
|
||||
background-image: url(../imgs/ic_jx.png);
|
||||
}
|
||||
.order-id {
|
||||
flex: 1;
|
||||
margin-left: .2rem;
|
||||
color: $blue;
|
||||
font-size: .32rem;
|
||||
white-space:nowrap;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
}
|
||||
.order-seq {
|
||||
width: .5rem;
|
||||
color: $sliver;
|
||||
}
|
||||
.order-status {
|
||||
width: 1.2rem;
|
||||
text-align: center;
|
||||
font-size: .24rem;
|
||||
background: $lightBlue;
|
||||
color: white;
|
||||
padding: .1rem 0;
|
||||
border-radius: .6rem;
|
||||
margin-left: .1rem;
|
||||
white-space:nowrap;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
}
|
||||
}
|
||||
// .refresh {
|
||||
// position: absolute;
|
||||
// width: 100%;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// z-index: -1;
|
||||
// text-align: center;
|
||||
// height: 1rem;
|
||||
// line-height: 1rem;
|
||||
// font-size: .32rem;
|
||||
// color: #ccc;
|
||||
// }
|
||||
}
|
||||
1
src/assets/svg/icon-activity.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552438839414" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6125" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M871.907023 286.645462H729.392192c32.358989-41.142026 38.408775-97.140411 15.581884-144.244218-22.825868-47.103808-70.526263-77.05598-122.868376-77.151148-45.157479 0-85.253686 22.128997-110.1057 56.140625a136.239917 136.239917 0 0 0-110.106724-56.140625c-52.342112 0.095167-100.042507 30.04734-122.868375 77.151148-22.826891 47.103808-16.776082 103.102193 15.581884 144.244218h-142.515855c-48.795333 0.12382-88.281649 39.724747-88.263229 88.52008v110.073978c0 40.096207 26.742061 74.011644 63.251579 84.867899v302.58141c-0.017396 47.605228 38.513152 86.23606 86.117357 86.342484h597.637426c47.592948-0.12382 86.10303-38.749536 86.085633-86.342484V570.107419c37.518498-11.208273 63.234183-45.711088 63.25158-84.867899V375.165542c0.017396-48.795333-39.467897-88.396259-88.264253-88.52008zM622.1057 118.125351c46.312792 0.106424 83.797521 37.690414 83.779102 84.004229 0.01842 46.275953-37.406958 83.844593-83.683934 84.003206h-83.811848v-84.132142c0.035816-46.276976 37.504172-83.802638 83.780125-83.908039l-0.063445 0.032746z m-220.2114 0c46.257533 0.141216 83.696214 37.651528 83.748402 83.908038v84.10042H401.733641c-46.25037-0.193405-83.637886-37.751812-83.619466-84.003206-0.017396-46.314839 37.46631-83.898829 83.780125-84.005252zM116.54332 485.23952V375.165542c0-19.632129 16.012695-35.644825 35.548634-35.644825h333.550748v181.362604H152.091954c-19.535939 0.001023-35.548634-16.012695-35.548634-35.643801z m63.250556 387.450332V573.759599h305.848826v332.429205H213.196637c-18.413372 0-33.402761-15.051811-33.402761-33.498952z m631.040187 33.498952H538.357298V573.759599h305.848826v298.930253c-0.001023 18.478863-14.956643 33.498952-33.372061 33.498952z m96.65434-420.949284c0 19.599384-16.013719 35.644825-35.548634 35.644824H538.325575V339.488994h333.550749c19.567661 0 35.548634 16.044418 35.548634 35.676548v110.073978h0.063445z" p-id="6126"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
src/assets/svg/icon-address.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552963597741" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3279" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M1024 975.3H0L109.3 548h131.1v56.9h-86.9L73.4 918.3h873.9L853 604.9h-76.1V548h118.4z" fill="#838383" p-id="3280"></path><path d="M510.6 844.5l-20-19.8C479.8 814 226.3 560.5 226.3 348.2c0-156.8 127.8-284.4 284.9-284.4s284.9 127.6 284.9 284.4c0 212.4-254.6 465.8-265.5 476.5l-20 19.8z m0.6-723.7c-125.7 0-227.9 102-227.9 227.4 0 156.6 168.4 351.7 227.3 415.1C569.7 699.9 739 504.6 739 348.2c0.1-125.4-102.2-227.4-227.8-227.4z" p-id="3281"></path><path d="M515.5 495.3c-78.5 0-142.4-63.9-142.4-142.4S437 210.4 515.5 210.4s142.4 63.9 142.4 142.4S594 495.3 515.5 495.3z m0-227.9c-47.1 0-85.5 38.3-85.5 85.5s38.3 85.5 85.5 85.5S601 400 601 352.8s-38.4-85.4-85.5-85.4z" p-id="3282"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
src/assets/svg/icon-addresslist.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552964416303" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4104" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M800 499.2c0 0-19.2 57.6 0 64 25.6 6.4 89.6-19.2 89.6-19.2L889.6 832c0 0-224 96-243.2 89.6-19.2-6.4-243.2-102.4-268.8-89.6-19.2 12.8-243.2 64-243.2 64L134.4 614.4c0 0 102.4-25.6 108.8-44.8 12.8-25.6 6.4-76.8-64-44.8C102.4 556.8 64 588.8 64 588.8l0 358.4c0 0 19.2 57.6 64 44.8 44.8-12.8 243.2-89.6 243.2-89.6s236.8 83.2 268.8 89.6c32 6.4 313.6-83.2 313.6-108.8 0-96 6.4-384 0-403.2C953.6 460.8 844.8 486.4 800 499.2M441.6 230.4c0-38.4 32-70.4 64-70.4 38.4 0 64 32 64 70.4 0 38.4-32 70.4-64 70.4C473.6 300.8 441.6 268.8 441.6 230.4zM684.8 217.6c-6.4-38.4-32-70.4-64-89.6 0 0-6.4-6.4-6.4-6.4-6.4 0-12.8-6.4-19.2-6.4-6.4 0-6.4-6.4-12.8-6.4-6.4 0-12.8 0-12.8-6.4-6.4 0-12.8-6.4-19.2-6.4C537.6 89.6 524.8 89.6 512 89.6c0 0 0 0 0 0 0 0 0 0 0 0-12.8 0-25.6 0-38.4 0-25.6 6.4-44.8 12.8-64 25.6 0 0 0 0 0 0C403.2 121.6 396.8 128 390.4 134.4c0 0-6.4 0-6.4 6.4C384 140.8 377.6 147.2 371.2 147.2 371.2 153.6 364.8 153.6 364.8 160c0 0-6.4 6.4-6.4 6.4C352 172.8 352 179.2 345.6 185.6c0 0 0 6.4 0 6.4 0 6.4-6.4 12.8-6.4 19.2 0 6.4-6.4 19.2-6.4 32C332.8 396.8 512 608 512 608s172.8-211.2 172.8-364.8C684.8 236.8 684.8 224 684.8 217.6zM512 697.6c0 0-243.2-243.2-243.2-454.4C262.4 32 512 32 512 32s243.2 0 243.2 211.2C755.2 454.4 512 697.6 512 697.6z" p-id="4105"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
1
src/assets/svg/icon-clear.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552556028106" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2836" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M511.3 42.6c-259 0-469 210-469 469s210 469 469 469 469-210 469-469-209.9-469-469-469z m219.2 618.5c19.4 19.4 19.4 51.3 0 70.7-19.4 19.4-51.3 19.4-70.7 0l-149-149-148 148c-19.4 19.4-51.3 19.4-70.7 0-19.4-19.4-19.4-51.3 0-70.7l148-148-148-148c-19.4-19.4-19.4-51.3 0-70.7 19.4-19.4 51.3-19.4 70.7 0l148 148 149-149c19.4-19.4 51.3-19.4 70.7 0 19.4 19.4 19.4 51.3 0 70.7l-149 149 149 149z" p-id="2837"></path></svg>
|
||||
|
After Width: | Height: | Size: 795 B |
1
src/assets/svg/icon-confirm.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552631339623" class="icon" style="" viewBox="0 0 1536 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15697" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="32"><defs><style type="text/css"></style></defs><path d="M1242.898 155.252c-26.894-26.895-71.191-26.895-98.085 0l-573.487 567.95-297.422-294.259c-26.894-26.894-71.191-26.894-98.086 0-26.894 26.895-26.894 70.4 0 96.504l346.465 342.51c13.447 13.447 30.85 19.775 49.043 19.775 17.403 0 35.596-7.119 49.043-19.775l622.53-616.201c27.685-26.104 27.685-69.61 0-96.504z m0 0" p-id="15698"></path></svg>
|
||||
|
After Width: | Height: | Size: 722 B |
1
src/assets/svg/icon-create.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552621953773" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12924" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M744.727273 744.727273v-139.636364a46.545455 46.545455 0 0 1 93.090909 0v139.636364h139.636363a46.545455 46.545455 0 0 1 0 93.090909h-139.636363v139.636363a46.545455 46.545455 0 0 1-93.090909 0v-139.636363h-139.636364a46.545455 46.545455 0 0 1 0-93.090909z m279.272727-139.636364a46.545455 46.545455 0 0 1-93.090909 0V186.181818a93.090909 93.090909 0 0 0-93.090909-93.090909H372.363636a279.272727 279.272727 0 0 0-279.272727 279.272727v465.454546a93.090909 93.090909 0 0 0 93.090909 93.090909h418.909091a46.545455 46.545455 0 0 1 0 93.090909H186.181818a186.181818 186.181818 0 0 1-186.181818-186.181818V372.363636a372.363636 372.363636 0 0 1 372.363636-372.363636h465.454546a186.181818 186.181818 0 0 1 186.181818 186.181818z" p-id="12925"></path><path d="M372.363636 0h93.090909v279.272727a186.181818 186.181818 0 0 1-186.181818 186.181818H0V372.363636a372.363636 372.363636 0 0 1 372.363636-372.363636z m0 93.090909a279.272727 279.272727 0 0 0-279.272727 279.272727h186.181818a93.090909 93.090909 0 0 0 93.090909-93.090909z" p-id="12926"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
src/assets/svg/icon-curposition.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1555297787963" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2677" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M629.983143 392.688794c-16.909393-16.884222-37.181736-30.429659-59.29766-39.572048-22.115924-9.148431-46.011996-13.889787-69.938274-13.889787s-47.855577 4.741356-69.938274 13.889787c-22.115924 9.14239-42.389274 22.657621-59.302695 39.572048-16.90738 16.879187-30.452817 37.152537-39.624406 59.211069-9.147424 22.087732-13.923014 45.954604-13.923014 69.85269 0 23.896072 4.747397 47.768986 13.923014 69.850676 9.143397 22.087732 22.687827 42.330875 39.624406 59.217111 16.913421 16.879187 37.186771 30.423617 59.302695 39.567014 22.082697 9.147424 46.013003 13.88878 69.938274 13.88878s47.82235-4.741356 69.938274-13.88878c22.086725-9.143397 42.389274-22.659634 59.29766-39.567014 16.90738-16.885228 30.457851-37.129379 39.600241-59.217111 9.14239-22.058532 13.917979-45.954604 13.917979-69.850676 0-23.898086-4.77559-47.764959-13.917979-69.85269C660.469186 429.841331 646.920729 409.596174 629.983143 392.688794L629.983143 392.688794zM904.481379 475.99731C888.113682 279.866873 744.298254 133.577563 547.877838 119.976748L547.877838 16.446233l-83.942844 0L463.934994 121.323941C273.011087 139.010639 121.601838 283.950742 105.239175 475.99731L1.594884 475.99731l0 85.64345 103.644291 0c16.362662 192.041533 165.962565 337.384385 356.885464 356.453517l0 104.877708 85.723999 0L547.848639 919.44147c196.39021-13.630014 340.235844-161.704507 356.601527-357.830916l103.669463 0 0-85.613244L904.481379 475.99731 904.481379 475.99731zM504.860277 849.072255c-181.378768 0-329.13509-148.875962-329.13509-328.673943 0-179.793953 149.110563-330.48329 329.13509-330.48329 181.40092 0 329.130055 150.689337 329.130055 330.48329C833.991339 700.1681 686.233004 849.072255 504.860277 849.072255L504.860277 849.072255zM504.860277 849.072255" p-id="2678"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
src/assets/svg/icon-delete.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553048546795" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12109" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M928.16 144H736V64a32 32 0 0 0-32-32H320a32 32 0 0 0-32 32v80H95.84a32 32 0 0 0 0 64H129.6l77.92 698.656A96 96 0 0 0 302.912 992h418.144a96.032 96.032 0 0 0 95.424-85.344L894.4 208h33.728a32 32 0 0 0 0.032-64zM352 96h320v48H352V96z m400.896 803.552a32 32 0 0 1-31.808 28.448H302.912a32 32 0 0 1-31.808-28.448L193.984 208h636.032l-77.12 691.552z" p-id="12110"></path><path d="M608 820.928a32 32 0 0 0 32-32V319.104a32 32 0 0 0-64 0v469.824a32 32 0 0 0 32 32zM432 820.928a32 32 0 0 0 32-32V319.104a32 32 0 0 0-64 0v469.824a32 32 0 0 0 32 32z" p-id="12111"></path></svg>
|
||||
|
After Width: | Height: | Size: 952 B |
1
src/assets/svg/icon-down.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553484098914" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1966" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M787.2 380.8c-9.6-9.6-22.4-12.8-35.2-12.8l-480 3.2c-12.8 0-25.6 3.2-35.2 12.8-19.2 19.2-19.2 48 0 67.2l240 240c3.2 3.2 9.6 6.4 12.8 9.6l3.2 3.2c16 6.4 38.4 3.2 51.2-9.6l240-243.2c22.4-22.4 19.2-51.2 3.2-70.4z" p-id="1967"></path></svg>
|
||||
|
After Width: | Height: | Size: 620 B |
1
src/assets/svg/icon-go.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552636528765" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16645" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M320.814545 123.997091L706.466909 502.039273l-380.97454499 371.665455c-18.827636 18.897455-23.133091 45.102545-9.72800002 58.600727 13.45163599 13.474909 39.586909 9.122909 58.41454501-9.774545L768 538.298182c6.097455-6.120727 10.49600001-13.009455 13.451636-19.968 2.885818-4.864 4.09600001-10.682182 3.909818-16.919273 0.139636-4.887273-0.67490901-9.448727-2.420364-13.54472699-0.139636-0.442182-0.349091-0.861091-0.488727-1.303273-0.232727-0.465455-0.372364-0.954182-0.628364-1.41963601-2.978909-7.424-7.633455-14.82472701-14.10327301-21.317818l-397.38181799-389.492364c-19.130182-19.2-45.730909-23.668364-59.415273-9.937455C297.216 78.10327299 301.684364 104.820364 320.814545 123.997091z" p-id="16646"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/svg/icon-goods.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552378857778" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8142" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M830.592 284.416C828.736 268.224 815.04 256 798.72 256L639.04 256 639.04 224c0-88.192-71.68-160-159.744-160S319.552 135.808 319.552 224L319.552 256 159.872 256C143.552 256 129.92 268.224 128.128 284.416l-63.936 576c-1.024 9.088 1.92 18.112 8 24.96C78.272 892.096 86.848 896 95.936 896l766.72 0c9.088 0 17.728-3.904 23.808-10.624 6.016-6.784 8.96-15.872 7.936-24.96L830.592 284.416zM383.488 224c0-52.928 43.008-96 95.808-96 52.864 0 95.872 43.072 95.872 96L575.168 256 383.488 256 383.488 224zM131.712 832l56.832-512 131.072 0 0 96c0 17.664 14.336 32 32 32 17.6 0 31.936-14.336 31.936-32L383.552 320l191.68 0 0 96C575.168 433.664 589.44 448 607.104 448c17.6 0 31.936-14.336 31.936-32L639.04 320l131.136 0 56.832 512L131.712 832z" p-id="8143"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/svg/icon-insert.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553048307206" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5760" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M455.111111 56.888889h113.777778v910.222222H455.111111z" p-id="5761"></path><path d="M967.111111 455.111111v113.777778H56.888889V455.111111z" p-id="5762"></path></svg>
|
||||
|
After Width: | Height: | Size: 552 B |
1
src/assets/svg/icon-mini.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553136908963" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6131" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M626.176 279.552c74.24 0 134.656 55.808 134.656 124.928 0 21.504-6.144 42.496-17.408 61.44-16.896 27.648-44.032 48.128-76.8 57.856-8.704 2.56-15.36 3.584-21.504 3.584-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6c1.024 0 3.072 0 5.632-1.024 22.016-6.144 39.424-18.944 49.152-35.84 6.656-10.752 9.728-22.528 9.728-34.816 0-40.448-37.376-73.728-82.944-73.728-15.872 0-31.232 4.096-45.056 11.776-24.064 13.824-38.4 36.864-38.4 61.952v214.528c0 43.52-24.064 83.456-64 105.984-21.504 12.288-45.568 18.432-70.144 18.432-74.24 0-134.656-55.808-134.656-124.928 0-21.504 6.144-42.496 17.408-61.44 16.896-27.648 44.032-48.128 76.8-57.856 9.216-2.56 15.36-3.584 21.504-3.584 14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6c-1.024 0-3.072 0-5.632 1.024-22.016 6.656-39.424 19.456-49.152 35.84-6.656 10.752-9.728 22.528-9.728 34.816 0 40.448 37.376 73.728 83.456 73.728 15.872 0 31.232-4.096 45.056-11.776 24.064-13.824 38.4-36.864 38.4-61.952V404.48c0-43.52 24.064-83.456 64-105.984 20.992-12.8 45.056-18.944 69.632-18.944z m-520.704 230.4c0 226.304 183.296 409.6 409.6 409.6s409.6-183.296 409.6-409.6-183.296-409.6-409.6-409.6-409.6 183.296-409.6 409.6z m-51.2 0c0-254.464 206.336-460.8 460.8-460.8s460.8 206.336 460.8 460.8-206.336 460.8-460.8 460.8-460.8-206.336-460.8-460.8z m0 0" p-id="6132"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/svg/icon-modify.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553131741449" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1162" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M884.329 926.072H142.056c-23.739 0-43.051-19.488-43.051-43.443V203.228c0-23.955 19.313-43.444 43.051-43.444h370.307c17.673 0 32 14.327 32 32 0 17.673-14.326 32-32 32H163.004v638.289H863.38V497.274c0-17.673 14.327-32 32-32s32 14.327 32 32v385.355c0 23.955-19.313 43.443-43.051 43.443z" p-id="1163"></path><path d="M334.451 783.482l37.361-197.519 393.876-466.021c9.105-10.774 22.329-17.291 36.279-17.879 13.929-0.596 27.606 4.773 37.55 14.706l70.177 70.098c18.154 18.133 19.381 47.712 2.79 67.339L516.002 723.312l-181.551 60.17z m97.115-169.071l-14.017 74.106 61.209-20.286 376.416-445.363-50.253-50.197-373.355 441.74z" p-id="1164"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
src/assets/svg/icon-more.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552621549381" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6238" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M305.454545 279.970909h631.156364c22.574545 0 40.96-25.134545 40.96-55.970909s-18.385455-55.970909-40.96-55.970909H305.454545c-22.574545 0-40.96 25.134545-40.96 55.970909s18.385455 55.970909 40.96 55.970909z m0 284.16h631.156364c22.574545 0 40.96-25.134545 40.96-55.854545 0-30.836364-18.385455-55.970909-40.96-55.970909H305.454545c-22.574545 0-40.96 25.134545-40.96 55.970909 0.116364 30.72 18.385455 55.854545 40.96 55.854545z m0 284.16h631.156364c22.574545 0 40.96-25.134545 40.96-55.970909s-18.385455-55.970909-40.96-55.970909H305.454545c-22.574545 0-40.96 25.134545-40.96 55.970909 0.116364 30.952727 18.385455 55.970909 40.96 55.970909z" p-id="6239"></path><path d="M46.661818 230.4c0 27.345455 14.545455 52.48 38.167273 66.094545 23.621818 13.614545 52.712727 13.614545 76.334545 0 23.621818-13.614545 38.167273-38.865455 38.167273-66.094545 0-27.345455-14.545455-52.48-38.167273-66.210909a76.438109 76.438109 0 0 0-76.334545 0c-23.621818 13.730909-38.167273 38.865455-38.167273 66.210909m0 281.018182c0 27.345455 14.545455 52.48 38.167273 66.210909 23.621818 13.614545 52.712727 13.614545 76.334545 0 23.621818-13.614545 38.167273-38.865455 38.167273-66.210909 0-27.229091-14.545455-52.48-38.167273-66.094546a76.438109 76.438109 0 0 0-76.334545 0c-23.621818 13.498182-38.167273 38.749091-38.167273 66.094546m0 281.018182c0 27.345455 14.545455 52.48 38.167273 66.094545 36.538182 21.061818 83.2 8.610909 104.378182-27.927273 6.749091-11.636364 10.24-24.785455 10.24-38.167272 0-27.345455-14.545455-52.48-38.167273-66.210909a76.438109 76.438109 0 0 0-76.334545 0c-23.738182 13.614545-38.283636 38.865455-38.283637 66.210909" p-id="6240"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
src/assets/svg/icon-order.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552378960463" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12241" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M287.798541 698.902768h274.649345v50.447887H287.798541z" p-id="12242"></path><path d="M927.453183 211.819726c-5.01409-11.870091-11.870091-22.409913-21.181973-31.721795-9.311882-8.697911-19.954032-16.167882-31.721795-21.181972-11.870091-5.62806-24.865794-8.083941-38.577795-8.083941h-74.69971v-13.098032c0-34.280004-28.037973-62.317977-62.317978-62.317977h-64.159888C611.667833 29.879884 564.289797 0 512 0s-99.667833 29.879884-122.691716 76.029979h-64.159888c-34.280004 0-62.317977 28.037973-62.317977 62.317977v11.870091h-74.69971c-13.098031 0-26.196063 3.069851-38.577796 8.083942-11.870091 5.01409-22.409913 11.870091-31.721795 21.181972-8.697911 9.311882-16.167882 19.954032-21.181972 31.721795-5.62806 11.870091-8.083941 24.865794-8.083942 38.577796v674.548615c0 13.098031 3.069851 26.196063 8.083942 38.577796 5.01409 11.870091 11.870091 22.409913 21.181972 31.721795 9.311882 8.697911 19.954032 16.167882 31.721795 21.181972 11.870091 5.62806 24.865794 8.083941 38.577796 8.083942h647.738582c13.712002 0 26.810033-2.455881 38.577796-7.469971s22.409913-11.870091 31.721795-21.181973c8.697911-9.311882 16.167882-19.954032 21.181972-31.721795 5.62806-11.870091 8.083941-24.865794 8.083942-38.577795V250.397522c0.102328-13.098031-2.967523-26.196063-7.981613-38.577796z m-614.788848-73.574098c0-6.856001 5.62806-12.484061 12.484061-12.484061h99.667833l5.62806-16.781853c11.870091-34.893974 45.433796-58.531828 82.169681-58.531828s70.401919 23.637854 82.169681 58.531828l5.628061 16.781853h98.439892c6.856001 0 12.484061 5.62806 12.484061 12.484061v112.151894H312.664335V138.245628z m573.038873 786.086539c0 27.424003-22.409913 49.833916-49.833917 49.833917h-647.738582c-27.424003 0-49.833916-22.409913-49.833917-49.833917V249.783552c0-27.424003 22.409913-49.833916 49.833917-49.833917h74.69971v100.281803h498.339162V200.563605h74.69971c27.424003 0 49.833916 22.409913 49.833917 49.833917v673.934645z" p-id="12243"></path><path d="M287.798541 474.598981h449.119217v50.447886H287.798541z" p-id="12244"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
1
src/assets/svg/icon-public.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553136848638" class="icon" style="" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5850" xmlns:xlink="http://www.w3.org/1999/xlink" width="32.03125" height="32"><defs><style type="text/css"></style></defs><path d="M503.171142 400.108793c17.65034 0 29.444278-11.816065 29.444278-29.422151 0-17.797856-11.771811-29.318889-29.444278-29.318889-17.672467 0-35.403941 11.521033-35.403941 29.318889C467.774576 388.300104 485.513426 400.108793 503.171142 400.108793L503.171142 400.108793zM338.476432 341.37513c-17.65034 0-35.499827 11.521033-35.499827 29.318889 0 17.606085 17.842111 29.422151 35.499827 29.422151 17.583958 0 29.355768-11.816065 29.355768-29.422151C367.817448 352.888786 356.06039 341.37513 338.476432 341.37513L338.476432 341.37513zM855.152703 588.457762c0-93.068111-86.348738-172.37294-192.339288-180.626484 0.147516-1.158004 0.206523-2.360263-0.044255-3.562522-21.249741-99.07203-127.800853-173.759594-247.864469-173.759594-135.670854 0-246.057393 94.58753-246.057393 210.859975 0 62.384695 31.848796 118.588452 92.197764 162.909761l-21.043218 63.24029c-1.349775 4.123084-0.125389 8.644462 3.156851 11.491529 1.998848 1.718566 4.499251 2.618417 7.036533 2.618417 1.630056 0 3.28224-0.390919 4.80166-1.135876l78.987669-39.527025 9.736084 1.984096c24.318082 4.993431 45.317045 9.323038 71.176674 9.323038 7.611847 0 15.341708-0.346664 22.9093-0.98836 3.068342-0.250778 5.664631-1.7997 7.4127-4.027198 28.478045 71.257808 106.97891 122.70416 199.353694 122.70416 23.661634 0 47.610925-5.70151 69.104068-11.085859l60.880028 33.287081c1.607929 0.877723 3.385502 1.327648 5.148323 1.327648 2.397142 0 4.794284-0.818716 6.726749-2.389766 3.392878-2.743805 4.786908-7.265184 3.525643-11.403019l-15.540855-51.69713C826.556644 686.799585 855.152703 637.521724 855.152703 588.457762L855.152703 588.457762zM435.992163 629.909877c-6.962775 0.597442-14.043563 0.907226-21.057969 0.907226-23.66901 0-43.709116-4.100957-66.869194-8.880489l-13.468249-2.729054c-2.316008-0.49418-4.76478-0.162268-6.881641 0.929353l-59.176213 29.613922 15.378587-46.194768c1.504668-4.521378-0.154892-9.455803-4.027198-12.177481C220.43379 549.941224 190.303561 499.461104 190.303561 441.369137c0-104.434251 100.753717-189.418463 224.608505-189.418463 109.486689 0 206.427106 66.603665 226.437709 155.194653-114.804656 1.504668-207.695747 82.203527-207.695747 181.312435 0 14.412355 2.190619 28.367408 5.878529 41.835657C438.418808 630.013138 437.238677 629.799239 435.992163 629.909877L435.992163 629.909877zM755.586493 715.403019c-3.569897 2.699551-5.089317 7.353694-3.8133 11.646422l10.141754 33.737006-41.629134-22.76916c-1.585802-0.885099-3.37075-1.327648-5.148323-1.327648-0.877723 0-1.755445 0.103261-2.611041 0.339288-22.326611 5.642503-45.420307 11.447274-67.916561 11.447274-104.493258 0-189.484845-71.796243-189.484845-160.033191 0-88.244324 84.998963-160.01844 189.484845-160.01844 102.487035 0 189.101302 73.278783 189.101302 160.01844C833.711191 632.439783 805.978103 677.535554 755.586493 715.403019L755.586493 715.403019zM579.695286 511.963121c-11.779186 0-23.550997 11.86032-23.550997 23.617379 0 11.830817 11.771811 23.528869 23.550997 23.528869 17.679843 0 29.377896-11.690677 29.377896-23.528869C609.073182 523.801314 597.37513 511.963121 579.695286 511.963121L579.695286 511.963121zM709.059813 511.963121c-11.602167 0-23.381353 11.86032-23.381353 23.617379 0 11.830817 11.779186 23.528869 23.381353 23.528869 17.620837 0 29.525412-11.690677 29.525412-23.528869C738.585225 523.801314 726.710153 511.963121 709.059813 511.963121L709.059813 511.963121zM709.059813 511.963121" p-id="5851"></path><path d="M512.014752 0C229.233145 0 0 229.233145 0 512.007376c0 282.759479 229.233145 511.985248 512.014752 511.985248 282.766855 0 511.992624-229.225769 511.992624-511.985248C1024.007376 229.233145 794.781607 0 512.014752 0zM512.014752 999.032845c-268.981445 0-487.032845-218.0514-487.032845-487.018094 0-268.974069 218.0514-487.032845 487.032845-487.032845s487.02547 218.0514 487.02547 487.032845C999.040221 780.981445 780.996197 999.032845 512.014752 999.032845z" p-id="5852"></path></svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
1
src/assets/svg/icon-return.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552631696336" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16472" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M698.115982 996.807111l-483.555555-483.555555a82.773333 82.773333 0 0 1 0-28.444445l483.555555-483.555555c3.726222-1.621333 14.250667-1.706667 28.444445 0l56.888889 56.888888c1.621333 14.848 1.706667 25.6 0 28.444445l-398.222223 398.222222a25.543111 25.543111 0 0 0 0 28.444445l398.222223 398.222222c1.592889 2.787556 1.763556 13.482667 0 28.444444l-56.888889 56.888889c-14.051556 1.621333-24.661333 1.706667-28.444445 0z" p-id="16473"></path></svg>
|
||||
|
After Width: | Height: | Size: 834 B |
1
src/assets/svg/icon-search.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552555983212" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1708" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M771.234762 696.266105l237.244632 237.244632a52.978526 52.978526 0 0 1-74.913685 74.913684l-237.298526-237.190737a431.157895 431.157895 0 1 1 74.913684-74.913684zM431.158973 754.526316A323.368421 323.368421 0 1 0 431.158973 107.789474a323.368421 323.368421 0 0 0 0 646.736842z" p-id="1709"></path></svg>
|
||||
|
After Width: | Height: | Size: 688 B |
1
src/assets/svg/icon-store.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552378502357" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7200" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M950.635165 366.916023 950.635165 366.916023c0-3.868977-1.936887-5.802466-1.936887-5.802466l-75.446447-187.647575c-13.541619-38.690368-50.296299-61.904829-94.789333-61.904829L252.281849 111.561154c-44.494033 0-79.311827 23.213062-92.852446 59.967942l-81.248713 191.516552c0 1.93209 0 1.93209-1.938086 3.868977-5.802466 17.410795-9.671443 36.75468-9.671443 54.165476 0 65.769009 36.75468 125.741747 92.858242 154.757075l0 0 0 0 0 0 0 0c23.213062 13.541619 52.22739 19.348881 83.181003 19.348881 52.233386 0 100.596396-23.217858 135.41299-63.842915 32.8905 38.691767 81.248713 61.904829 133.4809 61.904829 52.233386 0 100.591599-23.211862 133.482099-61.904829 32.884504 38.691767 81.248713 61.904829 135.414189 61.904829 32.884504 0 59.967742-7.738154 85.11789-19.342886 56.097566-30.951215 92.852246-90.918957 92.852246-154.761871C960.306408 403.670703 956.437631 384.328018 950.635165 366.916023L950.635165 366.916023 950.635165 366.916023 950.635165 366.916023zM836.495752 519.742207c-15.47271 7.739353-32.883305 11.603533-54.165476 11.603533-38.68677 0-75.446447-19.342886-94.789333-54.164277-1.93209-3.870176-3.868977-7.734556-7.739353-13.541619-5.802266-5.802266-15.473709-13.542818-30.947618-13.542818-13.54042 0-25.148749 5.807063-30.951215 13.542818-3.870176 5.807063-5.807063 9.671443-7.739353 13.541619-21.280972 32.889301-56.103562 54.164277-94.789333 54.164277-38.691567 0-73.513158-19.342886-94.789333-54.164277-1.935688-3.870176-3.870176-7.734556-7.740552-11.603533-15.47271-17.411795-48.36301-17.411795-61.903629-1.936887-5.801267 5.807063-7.734556 9.671443-9.672642 13.541619-21.279772 32.889301-56.097566 52.232187-94.789333 54.164277-21.279772 0-38.690368-3.86418-52.233386-11.603533l0 0 0 0c-36.75468-19.344085-59.966743-58.035652-59.966743-98.659509 0-11.60833 1.930891-25.149948 5.801267-36.75468l0-1.936887 79.316623-187.64038c1.930891-3.871375 5.802466-19.348881 30.951215-19.348881l528.114139 0c9.67624 0 27.082238 1.935688 34.821391 21.279772l75.446447 185.709489 0 3.870176c3.868977 11.609529 5.801267 25.151148 5.801267 36.75468C894.531604 463.639844 873.251831 500.398122 836.495752 519.742207L836.495752 519.742207 836.495752 519.742207 836.495752 519.742207zM861.647099 624.202982c-17.410795 0-32.883305 13.541619-32.883305 32.884504l0 174.104757c0 9.672642-7.739353 17.411995-17.411795 17.411995L207.787616 848.604238c-9.672642 0-17.407198-7.739353-17.407198-17.411995L190.380418 659.024174c0-17.410795-13.54042-32.889301-32.889301-32.889301l0 0c-17.410795 0-32.884504 13.541619-32.884504 32.889301l0 172.16787c0 44.495232 36.75468 81.248913 81.248713 81.248913l603.559387 0c44.495232 0 81.248713-36.753681 81.248713-83.181003l0-174.104757C892.599314 637.744601 879.058894 624.202982 861.647099 624.202982L861.647099 624.202982 861.647099 624.202982 861.647099 624.202982zM764.92088 397.869636l-512.64043 0c-17.410596 0-32.884504-13.541619-32.884504-32.8905 0-17.405999 13.54042-32.884504 32.884504-32.884504l512.639231 0c17.410795 0 32.889301 13.541619 32.889301 32.884504C797.810181 384.328018 782.331475 397.869636 764.92088 397.869636L764.92088 397.869636 764.92088 397.869636 764.92088 397.869636z" p-id="7201"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
1
src/assets/svg/icon-update.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553048579693" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13555" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M878.7968 545.7408c1.0752-11.1616 1.7408-22.3744 1.7408-33.7408s-0.6656-22.5792-1.7408-33.7408l85.5552-67.6352c18.5344-15.1552 23.296-41.2672 11.4176-61.9008l-91.2384-159.6416c-11.5712-20.2752-36.352-30.0032-59.8016-20.992L724.48 208.8448c-18.3808-13.2096-37.632-24.5248-57.4464-33.792l-15.2064-108.3392C648.2432 43.264 627.6608 25.6 604.0064 25.6L421.4784 25.6c-23.9616 0-44.0832 17.2544-47.872 41.472L358.4512 175.0528c-19.8656 9.3184-39.1168 20.6336-57.4976 33.792L200.448 167.936C178.7904 159.5392 152.576 168.8064 141.0048 189.0816L49.7664 348.672C37.888 369.4592 42.6496 395.5712 61.4912 410.88l85.1968 67.3792C145.6128 489.3696 144.9472 500.6336 144.9472 512s0.6656 22.6304 1.7408 33.7408L61.0304 613.376c-18.3808 15.2064-23.1424 41.2672-11.264 61.8496l91.2896 159.744c11.6224 20.224 36.9664 29.952 59.7504 20.8896l100.2496-40.7552c18.432 13.2096 37.6832 24.5248 57.4464 33.7408l15.2064 108.4928C377.4464 981.1456 397.568 998.4 421.4784 998.4l182.4768 0c23.6544 0 44.1856-17.664 47.9232-41.472l15.1552-108.032c19.8144-9.3184 39.0656-20.5824 57.4464-33.792l100.5056 40.96c5.632 2.2016 11.52 3.2768 17.5616 3.2768 17.2032 0 33.28-9.3184 41.984-24.4224l91.0848-159.5392c11.9296-20.5824 7.3216-46.6944-11.6736-62.4128L878.7968 545.7408zM843.9808 808.4992l-113.6128-46.2336c-8.4992-3.5328-18.1248-2.1504-25.344 3.4816-22.4256 17.408-46.3872 31.488-71.2704 41.8304-8.3456 3.4816-14.2336 11.1616-15.5136 20.1216l-16.7424 119.552-177.2032 2.6112-17.1008-122.1632c-1.2288-8.96-7.168-16.5888-15.5136-20.1216-24.6784-10.24-48.6912-24.3712-71.2704-41.8304-4.5568-3.4816-10.0864-5.3248-15.6672-5.3248-3.2256 0-6.5024 0.6144-9.6256 1.8944l-109.6192 47.2576-92.2112-156.3648 96.3584-76.0832c7.0656-5.5808 10.6496-14.4896 9.5232-23.3984C197.3248 540.0064 196.1472 526.1312 196.1472 512s1.1776-28.0064 2.9696-41.6256c1.1776-8.96-2.4064-17.8176-9.5232-23.3984L94.208 374.1184l87.296-158.6176 113.5104 46.1824c8.4992 3.4816 18.1248 2.1504 25.344-3.4304 22.4768-17.408 46.5408-31.5392 71.424-41.984 8.3456-3.4816 14.1824-11.1104 15.4624-20.0704L421.4784 76.8l179.712-2.6112 17.1008 122.112c1.2288 8.96 7.168 16.5888 15.5136 20.0704 24.7808 10.3424 48.7936 24.4224 71.3216 41.8816 7.2704 5.5808 16.896 6.912 25.344 3.4816l109.6192-47.2064 92.2624 156.2624-96.4096 76.1856c-7.0656 5.5808-10.7008 14.4384-9.5744 23.3472 1.7408 13.7216 3.0208 27.5968 3.0208 41.728s-1.2288 28.0064-3.0208 41.728c-1.1264 8.9088 2.5088 17.7664 9.5744 23.3472l95.3344 72.7552L843.9808 808.4992zM512.8192 318.976c-105.5744 0-191.4368 86.5792-191.4368 193.024 0 106.3936 85.8624 193.024 191.4368 193.024 105.5744 0 191.3856-86.5792 191.3856-193.024C704.2048 405.5552 618.3424 318.976 512.8192 318.976zM512.8192 653.824c-77.312 0-140.2368-63.5904-140.2368-141.824s62.9248-141.824 140.2368-141.824c77.312 0 140.1856 63.6416 140.1856 141.824S590.08 653.824 512.8192 653.824z" p-id="13556"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
1
src/assets/svg/icon-user.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552378994887" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13061" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M382.35 499.911a227.556 227.556 0 1 1 250.027 6.087C794.112 561.863 910.222 715.378 910.222 896a28.444 28.444 0 0 1-56.889 0c0-196.38-159.175-355.556-355.555-355.556S142.222 699.62 142.222 896a28.444 28.444 0 0 1-56.889 0c0-187.733 125.412-346.169 297.017-396.089zM512 483.556a170.667 170.667 0 1 0 0-341.334 170.667 170.667 0 0 0 0 341.334z" p-id="13062"></path></svg>
|
||||
|
After Width: | Height: | Size: 755 B |
1
src/assets/svg/loading.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552374587351" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4027" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M512 5.12A506.88 506.88 0 1 1 5.12 512 507.392 507.392 0 0 1 512 5.12m0-5.12a512 512 0 1 0 512 512A512 512 0 0 0 512 0z" fill="#dbdbdb" opacity=".01" p-id="4028"></path><path d="M1024 512a516.608 516.608 0 0 0-42.496-194.56A502.784 502.784 0 0 0 512 15.872a491.008 491.008 0 0 0-447.488 310.784A479.744 479.744 0 0 0 32.256 512a474.112 474.112 0 0 0 39.936 182.272 473.088 473.088 0 0 0 260.608 250.368 467.456 467.456 0 0 0 179.2 31.232 452.608 452.608 0 0 0 176.128-38.912 453.12 453.12 0 0 0 268.288-358.4h3.584A64 64 0 0 0 1024 517.12V512z m-102.4 169.984a440.32 440.32 0 0 1-98.816 141.312A436.736 436.736 0 0 1 512 944.128a436.224 436.224 0 0 1-163.84-36.352 440.32 440.32 0 0 1-136.192-95.744 437.248 437.248 0 0 1-88.064-139.264A409.6 409.6 0 0 1 358.4 138.752a402.944 402.944 0 0 1 307.2 7.168 389.12 389.12 0 0 1 125.44 89.088A373.248 373.248 0 0 1 870.4 363.52a376.832 376.832 0 0 1 25.6 148.48v5.12a64.512 64.512 0 0 0 57.344 64 460.8 460.8 0 0 1-31.232 102.4z" fill="#dbdbdb" p-id="4029"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
src/assets/svg/no-group.svg
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
1
src/assets/svg/no-store.svg
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,7 @@
|
||||
import Loading from './Loading.jsx';
|
||||
|
||||
export default {
|
||||
open (tip = '加载中') {
|
||||
Loading.show({tip});
|
||||
}
|
||||
};
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||