Commit 2cf35b25 authored by wty's avatar wty

Merge remote-tracking branch 'origin/dev' into dev

parents 9d2975f3 f6532b36
This source diff could not be displayed because it is too large. You can view the blob instead.
import React from 'react'
import './AdminIndex.scss'
import { Layout, Menu, Breadcrumb, Button } from 'antd';
import ToolModal from '../../modal/ToolModal'
import PublishModal from '../../modal/PublishModal'
import TypeModal from '../../modal/TypeModal'
import PageModal from '../../modal/PageModal'
import { useContext, useEffect, useState } from "react";
function AdminIndex() {
const [visible, setVisible] = useState(false)
const [publish, setPublish] = useState(false)
const [typeModal, setTypeModal] = useState(false)
const [pageModal, setpageModal] = useState(false)
return (
<div className='admin'>
<Button onClick={() => setVisible(true)}>新建工具盒</Button>
<Button onClick={() => setTypeModal(true)}>新建类型</Button>
<Button onClick={() => setPublish(true)}>发布</Button>
<Button onClick={() => setpageModal(true)}>页面管理</Button>
{visible && <ToolModal
visible={visible}
onCancel={() =>
setVisible(false)
}
/>}
{publish && <PublishModal
visible={publish}
onCancel={() =>
setPublish(false)
}
/>}
{typeModal && <TypeModal
visible={typeModal}
onCancel={() =>
setTypeModal(false)
}
/>}
{pageModal && <PageModal
visible={pageModal}
onCancel={() =>
setpageModal(false)
}
/>}
</div>
)
}
export default AdminIndex
.admin {
float: left;
.ant-btn{
width: 100px !important;
}
width: 100px;
// height: 100px;
// border: 1px solid red;
#components-layout-demo-top-side .logo {
float: left;
width: 120px;
height: 31px;
margin: 16px 24px 16px 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-row-rtl #components-layout-demo-top-side .logo {
float: right;
margin: 16px 0 16px 24px;
}
.site-layout-background {
background: #fff;
}
}
\ No newline at end of file
...@@ -5,16 +5,18 @@ import followed from '../../static/followed.png' ...@@ -5,16 +5,18 @@ import followed from '../../static/followed.png'
import setting from '../../static/setting.svg' import setting from '../../static/setting.svg'
import trash from '../../static/trash.svg' import trash from '../../static/trash.svg'
import dragIcon from '../../static/dragIcon.svg' import dragIcon from '../../static/dragIcon.svg'
import {useContext, useState} from "react"; import { useContext, useState } from "react";
import {PopContext, Root} from "../../dataCenter/Root"; import { PopContext, Root } from "../../dataCenter/Root";
import PopToolBoxConfig from "../Pop_ToolBoxConfig/Pop_toolBoxConfig"; import PopToolBoxConfig from "../Pop_ToolBoxConfig/Pop_toolBoxConfig";
import ToolModal from "../../modal/ToolModal"
function ContentItem(props) { function ContentItem(props) {
const [visible, setVisible] = useState(false)
const {fetchData, updateIndex} = useContext(Root) const { fetchData, updateIndex } = useContext(Root)
const {showPop} = useContext(PopContext) const { showPop } = useContext(PopContext)
const {toolBoxIcon, toolBoxName, toolBoxDesc, toolBoxUrl, follow, toolBoxId} = props.value const { toolBoxIcon, toolBoxName, toolBoxDesc, toolBoxUrl, follow, toolBoxId } = props.value
const [itemIcon, setItemIcon] = useState(toolBoxIcon) const [itemIcon, setItemIcon] = useState(toolBoxIcon)
...@@ -22,7 +24,7 @@ function ContentItem(props) { ...@@ -22,7 +24,7 @@ function ContentItem(props) {
window.location.href = url window.location.href = url
} }
const deleteItem = toolBoxId => { const deleteItem = toolBoxId => {
fetchData('/delete/deleteToolBoxById', {toolBoxId}) fetchData('/delete/deleteToolBoxById', { toolBoxId })
.then(() => updateIndex()) .then(() => updateIndex())
} }
...@@ -30,20 +32,28 @@ function ContentItem(props) { ...@@ -30,20 +32,28 @@ function ContentItem(props) {
<div className="content-item"> <div className="content-item">
<div className="content-adminTool"> <div className="content-adminTool">
<img src={dragIcon} alt="" /> <img src={dragIcon} alt="" />
<img src={setting} alt="" onClick={() => showPop((<PopToolBoxConfig value={props.value}/>))}/> <img src={setting} alt="" onClick={() => setVisible(true)} />
<img src={trash} alt="" onClick={() => deleteItem(toolBoxId)}/> <img src={trash} alt="" onClick={() => deleteItem(toolBoxId)} />
</div> </div>
<div className="item-icon" onClick={() => jumpUrl(toolBoxUrl)}> <div className="item-icon" onClick={() => jumpUrl(toolBoxUrl)}>
<img src={itemIcon} alt='' onError={(e) => setItemIcon(defaultIcon)}/> <img src={itemIcon} alt='' onError={(e) => setItemIcon(defaultIcon)} />
</div> </div>
<div className="item-name" onClick={() => jumpUrl(toolBoxUrl)}>{toolBoxName}</div> <div className="item-name" onClick={() => jumpUrl(toolBoxUrl)}>{toolBoxName}</div>
<div className="item-desc">{toolBoxDesc}</div> <div className="item-desc">{toolBoxDesc}</div>
<a className='item-url' href={toolBoxUrl}>{toolBoxUrl}</a> <a className='item-url' href={toolBoxUrl}>{toolBoxUrl}</a>
<div className="follow"> <div className="follow">
<img className='icon-follow' src={follow ? followed : notFollow} alt=""/> <img className='icon-follow' src={follow ? followed : notFollow} alt="" />
收藏 收藏
</div> </div>
{visible && <ToolModal
visible={visible}
onCancel={() =>
setVisible(false)
}
data={props.value}
/>}
</div> </div>
) )
} }
......
const apiConfig = { const apiConfig = {
domain: 'http://' + window.location.hostname + ':3001', domain: 'http://' + '172.16.231.162' + ':3001',
} }
export default apiConfig export default apiConfig
import React, { useState } from 'react';
import { Button, Modal, Form, Input, Radio, Select, Table, Space } from 'antd';
import PublishModal from "./PublishModal"
function PageModal({ visible, onCancel, onPublish }) {
const [publish, setPublish] = useState(false)
const [pageData, setpageData] = useState('')
const onChangePage = (values) => {
console.log(values);
setpageData(values);
setPublish(true)
};
const onRemovePage = (values) => {
console.log(values);
// setVisible(false);
};
const columns = [
{
title: '页面名称',
dataIndex: 'name',
width: 200,
},
{
title: '页面类型',
dataIndex: 'age',
width: 300,
},
{
title: '操作',
key: 'action',
width: 100,
render: (text, record) => (
<Space size="middle">
<a onClick={() => onChangePage(record)}>替换</a>
{/* <a onClick={() => onRemovePage(record)}>删除</a> */}
</Space>
),
},
];
const data = [
{
key: '1',
name: '1 Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: '2 Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: '3 Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
{
key: '4',
name: '4 Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '5',
name: '5 Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '6',
name: '6 Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
{
key: '7',
name: '7 Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '8',
name: '8 Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '9',
name: '9 Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
{
key: '10',
name: '10 Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '11',
name: '11 Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '12',
name: '12 Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
];
return (
<>
<Modal
visible={visible}
title="页面管理"
okText="确定"
cancelText="取消"
width='1000px'
onCancel={onCancel}
onOk={onCancel}
>
<Table columns={columns} dataSource={data} pagination={{ pageSize: 10 }} size="middle" />
</Modal>
{publish && <PublishModal
visible={publish}
onCancel={() =>
setPublish(false)
}
data={pageData}
/>}
</>
)
}
export default PageModal
import './PublishModal.scss'
import React, { useState, useEffect } from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2'
import { Button, Modal, Form, Input, Radio, Select, message } from 'antd';
import 'codemirror/addon/display/autorefresh';
import 'codemirror/addon/comment/comment';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/keymap/sublime';
import 'codemirror/theme/eclipse.css';
import 'codemirror/theme/monokai.css';
import 'codemirror/lib/codemirror.js';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/solarized.css'
import 'codemirror/mode/javascript/javascript'
import 'codemirror/addon/selection/active-line';
import 'codemirror/addon/fold/foldgutter.css';
const { Option } = Select;
const PublishModal = ({ visible, onCancel, data }) => {
const [code, setcode] = useState('')
const [pageName, setPageName] = useState('')
const [oldCode, setoldCode] = useState('')
const onCreate = (values) => {
console.log(code);
if (!code || !pageName) {
message.error('请补全信息!')
return
}
fetch('http://172.16.231.162:3001/submit/release', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
pageName: pageName,
code: code
})
})
.then(response => response.json())
.then(data => console.log(data));
onCancel()
};
useEffect(() => {
// setPageName(data.name)
}, [])
return (
<Modal
visible={visible}
title="发布"
okText="发布"
cancelText="取消"
onCancel={onCancel}
onOk={onCreate}
width='1000px'
>
<Form.Item
name="pageName"
label="页面名称"
rules={[
{
required: true,
message: '请输入页面名称!',
},
]}
>
<Input placeholder="请输入页面名称" value={pageName} onChange={(e) => { setPageName(e.target.value) }} />
</Form.Item>
<Form.Item
name="type"
label="布局代码"
rules={[
{
required: true,
message: '请输入页面名称!',
},
]}
>
<div className='codeMain'>
<CodeMirror
onChange={(editor, data, value) => {
setcode(value)
}}
value={oldCode}
options={{
styleActiveLine: true,//光标代码高亮
lineNumbers: true,
theme: 'monokai',
tabSize: 2,
keyMap: 'sublime',
mode: 'text/javascript',
smartIndent: true, //自动缩进
lineWrapping: true,
autofocus: true
}}
/>
</div>
</Form.Item>
</Modal>
);
};
export default PublishModal
\ No newline at end of file
.codeMain{
.CodeMirror{
height: 600px !important;
width: 850px;
}
}
\ No newline at end of file
import React, { useState,useEffect } from 'react';
import { Button, Modal, Form, Input, Radio, Select } from 'antd';
const { Option } = Select;
const ToolModal = ({ visible, onCancel, data }) => {
const [form] = Form.useForm();
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 18 },
};
const onCreate = (values) => {
console.log('Received values of form: ', values);
// setVisible(false);
};
const onGenderChange = (value) => {
switch (value) {
case 'male':
form.setFieldsValue({
note: 'Hi, man!',
});
return;
case 'female':
form.setFieldsValue({
note: 'Hi, lady!',
});
return;
case 'other':
form.setFieldsValue({
note: 'Hi there!',
});
}
};
useEffect(() => {
data && form.setFieldsValue({
name: data.toolBoxName,
icon: data.toolBoxIcon,
url: data.toolBoxUrl,
depict: data.toolBoxDesc,
})
}, [])
return (
<Modal
visible={visible}
title={data ? '修改工具箱' : '新建工具箱'}
okText="确定"
cancelText="取消"
onCancel={onCancel}
onOk={() => {
form
.validateFields()
.then((values) => {
form.resetFields();
onCreate(values);
})
.catch((info) => {
console.log('Validate Failed:', info);
});
}}
>
<Form
form={form}
// layout="vertical"
{...formItemLayout}
name="form_in_modal"
initialValues={{
modifier: 'public',
}}
>
<Form.Item
name="name"
label="名称"
rules={[
{
required: true,
message: '请输入名称!',
},
]}
>
<Input placeholder="请输入名称" />
</Form.Item>
<Form.Item name="icon"
label="图标"
rules={[
{
required: true,
message: '请输入图标url!',
},
]}
>
<Input placeholder="请输入图标url" />
</Form.Item>
<Form.Item
name="depict"
label="描述"
rules={[
{
required: true,
message: '请输入描述!',
},
]}
>
<Input placeholder="请输入描述" />
</Form.Item>
<Form.Item
name="url"
label="链接"
rules={[
{
required: true,
message: '请输入链接!',
},
]}
>
<Input placeholder="请输入链接" />
</Form.Item>
{!data && <Form.Item
name="type"
label="类型"
rules={[
{
required: true,
message: '请选择类型!',
},
]}
>
<Select
placeholder="请选择类型"
onChange={onGenderChange}
allowClear
>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>}
</Form>
</Modal>
);
};
export default ToolModal
\ No newline at end of file
import React, { useState } from 'react';
import { Button, Modal, Form, Input, Radio, Select } from 'antd';
const { Option } = Select;
const TypeModal = ({ visible, onCancel }) => {
const [form] = Form.useForm();
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 18 },
};
const onCreate = (values) => {
console.log('Received values of form: ', values);
// setVisible(false);
};
return (
<Modal
visible={visible}
title="新建类型"
okText="确定"
cancelText="取消"
onCancel={onCancel}
onOk={() => {
form
.validateFields()
.then((values) => {
form.resetFields();
onCreate(values);
})
.catch((info) => {
console.log('Validate Failed:', info);
});
}}
>
<Form
form={form}
// layout="vertical"
{...formItemLayout}
name="form_in_modal"
initialValues={{
modifier: 'public',
}}
>
<Form.Item
name="type"
label="类型"
rules={[
{
required: true,
message: '请输入类型!',
},
]}
>
<Input placeholder="请输入类型" />
</Form.Item>
</Form>
</Modal>
);
};
export default TypeModal
\ No newline at end of file
...@@ -12,7 +12,7 @@ function Index() { ...@@ -12,7 +12,7 @@ function Index() {
setPop(popComponent) setPop(popComponent)
} }
const getUser = ()=>{ const getUser = ()=>{
fetchData('/users/getUser', {}, 'userInfo') fetchData('/users/getUser', {userId:'100001'}, 'userInfo')
.catch(res => .catch(res =>
res.code === 70001 && (window.location.href = '/login') res.code === 70001 && (window.location.href = '/login')
) )
......
import './index.scss' import './index.scss'
import ToolType from "../../component/ToolType/ToolType"; import ToolType from "../../component/ToolType/ToolType";
import Content from "../../component/ContentAdmin/Content"; import Content from "../../component/ContentAdmin/Content";
import {useContext, useEffect, useState} from "react"; import { useContext, useEffect, useState } from "react";
import PopAddToolBox from "../../component/Pop_addToolBox/Pop_addToolBox"; import PopAddToolBox from "../../component/Pop_addToolBox/Pop_addToolBox";
import {PopContext, Root} from "../../dataCenter/Root"; import { PopContext, Root } from "../../dataCenter/Root";
import PopAddType from "../../component/Pop_addType/Pop_addType"; import PopAddType from "../../component/Pop_addType/Pop_addType";
import logo from '../../static/logo.png' import logo from '../../static/logo.png'
import AdminIndex from '../../component/AdminIndex/AdminIndex'
function IndexAdmin() { function IndexAdmin() {
const {updateIndex} = useContext(Root) const { updateIndex } = useContext(Root)
const {fetchData, dataCenter} = useContext(Root)
const [pop, setPop] = useState() const [pop, setPop] = useState()
const showPop = popComponent => { const showPop = popComponent => {
setPop(popComponent) setPop(popComponent)
} }
const getUser = ()=>{
fetchData('/users/getUser', {userId:'100001'}, 'userInfo')
.catch(res =>
res.code === 70001 && (window.location.href = '/login')
)
}
useEffect(()=>{
getUser()
},[])
useEffect(() => { useEffect(() => {
updateIndex() updateIndex()
// dataCenter()
}, []) }, [])
return ( return (
<PopContext.Provider value={{hidePop: () => setPop(''), showPop: popName => showPop(popName)}}> <PopContext.Provider value={{hidePop: () => setPop(''), showPop: popName => showPop(popName)}}>
<div className="indexAdmin"> <div className="index">
<div className="welcome-top">
<span>欢迎您!
<span className="welcome-uname">{dataCenter?.userInfo?.uname}</span>
<a className="login-btn">退出登录</a>
</span>
</div>
<div className="nav"> <div className="nav">
<div className="nav-title"><img src={logo} alt=""/></div> <div className="nav-title">
<img src={logo} alt=""/>
</div>
<div className="nav-weather"><iframe width="360" height="40" frameBorder="0" scrolling="no" hspace="0" src="https://i.tianqi.com/?c=code&a=getcode&id=40&icon=1"/></div>
</div> </div>
<div className="adminTool"> <div className="tool-nav">
<ToolType/>
</div>
<div className="container">
<Content/>
</div>
{
pop
}
<div className></div>
<div className="index-footer">
兑吧研发中心·杭州兑吧网络科技游戏公司版权所有
<br/>
浙ICP备14017299号-1
</div>
<AdminIndex />
{/* <div className="adminTool">
<button className='btn-admin' onClick={() => setPop((<PopAddToolBox/>))}>新建工具盒</button> <button className='btn-admin' onClick={() => setPop((<PopAddToolBox/>))}>新建工具盒</button>
<button className='btn-admin' onClick={() => setPop((<PopAddType/>))}>新建类型</button> <button className='btn-admin' onClick={() => setPop((<PopAddType/>))}>新建类型</button>
</div> </div>
...@@ -38,8 +78,11 @@ function IndexAdmin() { ...@@ -38,8 +78,11 @@ function IndexAdmin() {
</div> </div>
{ {
pop pop
} } */}
</div> </div>
</PopContext.Provider> </PopContext.Provider>
) )
} }
......
...@@ -2,38 +2,63 @@ ...@@ -2,38 +2,63 @@
body { body {
background: $backgroundColor; background: $backgroundColor;
} }
.indexAdmin { .index {
width: 100%; width: 100%;
height: 100%; height: 100%;
color: $fontColor; color: $fontColor;
background: #f1f1f1;
.adminTool{ font-size: 14px;
position: absolute; font-style: normal;
width: 160px; .welcome-top{
background-color: #444;
color: #fff;
text-align: right;
padding: 7px 10px;
font-size: 13px;
.welcome-uname{
padding: 0px 4px;
font-weight: bold;
}
.login-btn{
cursor: pointer;
text-decoration: underline;
}
}
.index-footer{
text-align: center; text-align: center;
top: 60px; color: #b3b3b3;
.btn-admin{ line-height: 26px;
width: 120px; margin-top: 12px;
height: 35px; }
.nav-weather{
float: right;
padding-top: 18px;
&::after{
display: block;
clear: both;
content: "";
} }
} }
.nav { .nav {
width: 100%; width: 100%;
height: 40px; height: 60px;
background: $topBarBg; //background: $topBarBg;
color: #fff; color: #fff;
max-width: 1190px;
min-width: 612px;
margin: auto;
border-bottom: 2px solid #dedede;
.nav-title { .nav-title {
width: 150px; width: 150px;
height: 40px; height: 50px;
font-size: 32px; font-size: 32px;
line-height: 40px; line-height: 50px;
font-weight: bold;; font-weight: bold;;
text-align: center; text-align: center;
margin-left: 20px; margin-left: 20px;
float: left;
margin-top: 6px;
img { img {
width: 100%; width: 100%;
} }
...@@ -43,14 +68,18 @@ body { ...@@ -43,14 +68,18 @@ body {
.tool-nav { .tool-nav {
width: 100%; width: 100%;
min-width: 612px; min-width: 612px;
max-width: 1190px;
box-sizing: border-box; box-sizing: border-box;
margin: 0 auto 0;
} }
} }
.container { .container {
width: 100%; width: 100%;
min-width: 612px; min-width: 612px;
padding: 20px 180px; max-width: 1190px;
padding: 20px 0;
margin: 0 auto 0;
box-sizing: border-box; box-sizing: border-box;
} }
...@@ -8,7 +8,7 @@ function Login(props) { ...@@ -8,7 +8,7 @@ function Login(props) {
const [needLogin,setNeedLogin] = useState(false) const [needLogin,setNeedLogin] = useState(false)
const [input, setInput] = useFormState() const [input, setInput] = useFormState()
const getUser = ()=>{ const getUser = ()=>{
fetchData('/users/getUser', {}, 'userInfo') fetchData('/users/getUser', {userId:'100001'}, 'userInfo')
.then(res => res.data.uid && (window.location.href = '/index')) .then(res => res.data.uid && (window.location.href = '/index'))
.catch(res => .catch(res =>
res.code === 70001 && setNeedLogin(true) res.code === 70001 && setNeedLogin(true)
...@@ -16,7 +16,7 @@ function Login(props) { ...@@ -16,7 +16,7 @@ function Login(props) {
} }
const doLogin = () => { const doLogin = () => {
if (needLogin){ if (needLogin){
fetchData('/users/login',{userId: input.userId}) fetchData('/users/login',{userId: '100001'})
.then(()=>{ .then(()=>{
getUser() getUser()
}) })
......
...@@ -3591,6 +3591,11 @@ code-point-at@^1.0.0: ...@@ -3591,6 +3591,11 @@ code-point-at@^1.0.0:
resolved "http://npm.dui88.com:80/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" resolved "http://npm.dui88.com:80/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codemirror@^5.62.3:
version "5.62.3"
resolved "https://registry.nlark.com/codemirror/download/codemirror-5.62.3.tgz?cache=0&sync_timestamp=1629450520293&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcodemirror%2Fdownload%2Fcodemirror-5.62.3.tgz#5cfdee6931c8b2d1b39ae773aaaaec2cc6b5558e"
integrity sha1-XP3uaTHIstGzmudzqqrsLMa1VY4=
collect-v8-coverage@^1.0.0: collect-v8-coverage@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "http://npm.dui88.com:80/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" resolved "http://npm.dui88.com:80/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
...@@ -10105,6 +10110,11 @@ react-app-polyfill@^2.0.0: ...@@ -10105,6 +10110,11 @@ react-app-polyfill@^2.0.0:
regenerator-runtime "^0.13.7" regenerator-runtime "^0.13.7"
whatwg-fetch "^3.4.1" whatwg-fetch "^3.4.1"
react-codemirror2@^7.2.1:
version "7.2.1"
resolved "https://registry.npm.taobao.org/react-codemirror2/download/react-codemirror2-7.2.1.tgz#38dab492fcbe5fb8ebf5630e5bb7922db8d3a10c"
integrity sha1-ONq0kvy+X7jr9WMOW7eSLbjToQw=
react-dev-utils@^11.0.3: react-dev-utils@^11.0.3:
version "11.0.4" version "11.0.4"
resolved "http://npm.dui88.com:80/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a" resolved "http://npm.dui88.com:80/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment