Commit def0dbf3 authored by wty's avatar wty

新增:新建工具盒,新建类型

优化接口路由
parent 6cdad966
......@@ -6,6 +6,9 @@ const logger = require('morgan');
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const databaseRouter = require('./routes/dataBase/dataBase')
const queryRouter = require('./routes/query')
const addRouter = require('./routes/add')
const deleteRouter = require('./routes/delete')
const app = express();
global.domain = 'http://127.0.0.1:3001'
......@@ -32,13 +35,16 @@ app.use((req, res, next) => {
})
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/database', databaseRouter)
app.use('/query', queryRouter)
app.use('/add', addRouter)
app.use('/delete',deleteRouter)
module.exports = app;
const express = require('express')
const request = require("request");
const router = express.Router()
router.get('/addToolBox', (req, res) => {
const {name,icon,desc,url} = req.query
const data = encodeURI(JSON.stringify({name,icon,desc,url}))
// res.send({success: true})
request(`${domain}/database/addData?tableName=toolBox&data=${data}`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
err
})
}
})
})
router.get('/addType', (req, res) => {
const {name} = req.query
const data = encodeURI(JSON.stringify({name}))
// res.send({success: true})
request(`${domain}/database/addData?tableName=type&data=${data}`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
err
})
}
})
})
module.exports = router
......@@ -8,7 +8,7 @@ const tablePath = {
type: path.join(__dirname, './type.json')
}
const add = (tableName,addData) => {
const add = (tableName, addData) => {
fs.readFile(tablePath[tableName], (err, data) => {
if (err) {
console.error(err)
......@@ -16,7 +16,7 @@ const add = (tableName,addData) => {
}
const _data = JSON.parse(data.toString())
const lastId = _data[_data.length - 1]?.id || 0
_data.push(Object.assign({id: lastId + 1},addData))
_data.push(Object.assign({id: lastId + 1}, addData))
fs.writeFile(tablePath[tableName], JSON.stringify(_data), (err) => {
if (err) {
console.error(err)
......@@ -24,7 +24,24 @@ const add = (tableName,addData) => {
}
console.log('数据添加成功')
})
})
}
const deleteData = (tableName, dataId) => {
fs.readFile(tablePath[tableName], (err, data) => {
if (err) {
console.error(err)
throw err
}
const _data = JSON.parse(data.toString())
const newData = _data.filter(v => +v.id !== +dataId)
fs.writeFile(tablePath[tableName], JSON.stringify(newData), (err) => {
if (err) {
console.error(err)
return err
}
console.log('数据删除成功')
})
})
}
......@@ -35,13 +52,13 @@ const queryTable = (tableName) => {
router.get('/queryTable', (req, res) => {
const {tableName} = req.query
console.log('查询:',tableName)
console.log('查询:', tableName)
const data = queryTable(tableName)
if (data){
if (data) {
res.send({
data
})
}else {
} else {
res.send({
Error: data
})
......@@ -49,21 +66,34 @@ router.get('/queryTable', (req, res) => {
})
router.get('/addData', (req, res) => {
const {tableName,data} = req.query
const {tableName, data} = req.query
const _data = JSON.parse(data)
try{
add(tableName,_data)
try {
add(tableName, _data)
res.send({
data:'通了'
data: '数据添加成功!'
})
}catch (e){
} catch (e) {
console.log(e)
res.send({
message: e
e
})
}
})
router.get('/deleteDataById', (req, res) => {
const {tableName, dataId} = req.query
try {
deleteData(tableName, dataId)
res.send({
data: '数据删除成功!'
})
} catch (e) {
console.log(e)
res.send({
e
})
}
})
......
[{"id":1,"name":"星速台","icon":"http://yun.dui88.com/polaris/favicon1.ico","desc":"项目发布,运营等功能","url":"http://yun.dui88.com/polaris/favicon1.ico"}]
\ No newline at end of file
[{"id":1,"name":"星火组件库文档","icon":"https://yun.duiba.com.cn/editor/spark/favicon.ico","desc":"星火组件库文档,烽火台3.0文档也在里头哦~","url":"http://spark.duiba.com.cn/docs/"},{"id":10,"name":"测试数据","icon":"https://yun.duiba.com.cn/spark/assets/511a27ba957e5cf744e96e914e65383b3ba8dae3.png","desc":"测试数据","url":"www.baidu.com"},{"id":14,"name":"1","icon":"1","desc":"1","url":"1"}]
\ No newline at end of file
const express = require('express')
const request = require('request')
const router = express.Router()
router.get('/deleteToolBoxById', (req, res) => {
const {id} = req.query
request(`${domain}/database/deleteDataById?tableName=toolBox&dataId=${id}`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
err
})
}
})
})
module.exports = router
......@@ -3,52 +3,6 @@ const request = require('request')
let router = express.Router();
/* GET home page. */
router.get('/queryType', (req, res) => {
request(`${domain}/database/queryTable?tableName=type`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
error: err
})
}
})
});
router.get('/queryToolBox', (req, res) => {
request(`${domain}/database/queryTable?tableName=toolBox`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
error: err
})
}
})
});
router.get('/addToolBox', (req, res) => {
request(`${domain}/database/queryTable?tableName=toolBox`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
error: err
})
}
})
})
module.exports = router;
const express = require('express')
const request = require("request");
const router = express.Router()
router.get('/queryType', (req, res) => {
request(`${domain}/database/queryTable?tableName=type`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
error: err
})
}
})
});
router.get('/queryToolBox', (req, res) => {
request(`${domain}/database/queryTable?tableName=toolBox`, {}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const data = JSON.parse(body)
res.send({
success: true,
data: data.data
})
} else {
res.send({
error: err
})
}
})
});
module.exports = router
.Pop-container {
width: 300px;
position: absolute;
background: #DBDCE0;
border-radius: 5px;
border: 2px solid #DBDCE0;
.Pop-title {
width: 300px;
text-align: center;
}
.Pop-tool {
height: 24px;
border-radius: 5px 5px 0 0;
background: rgba(0, 0, 0, 0.7);
button {
border-radius: 5px;
}
.close {
width: 23px;
height: 23px;
font-size: 18px;
color: #ffffff;
text-align: left;
background: rgba(0, 0, 0, 0.8);
}
}
.input-group {
margin-top: 30px;
position: relative;
text-align: center;
input {
width: 250px;
height: 30px;
border: 0;
padding: 0 8px;
background-color: #FEFEFE;
&:required {
&:valid {
& + span {
top: -24px;
}
}
}
&:focus:required {
&:invalid {
& + span {
top: -24px;
}
}
}
}
span {
position: absolute;
top: 4px;
left: 22px;
transition: top 0.5s;
font-size: 14px;
font-weight: bold;
}
}
.Pop-bottom {
width: 100%;
padding: 20px;
box-sizing: border-box;
text-align: center;
.btn-submit-addToolBox {
width: 100px;
height: 40px;
font-size: 14px;
}
}
}
......@@ -8,13 +8,14 @@ function Content(props) {
return (
<div className="content">
{
dataCenter?.toolBox?.length && dataCenter.toolBox.map(v => {
dataCenter?.toolBox?.length ? dataCenter.toolBox.map(v => {
return (
<ContentItem key={v.id} value={v}/>
)
})
:
'没有数据了!'
}
</div>
)
}
......
......@@ -2,14 +2,27 @@ import './ContentItem.scss'
import defaultIcon from '../../static/defaultIcon.png'
import notFollow from '../../static/notFollow.png'
import followed from '../../static/followed.png'
import setting from '../../static/setting.svg'
import trash from '../../static/trash.svg'
import {useContext} from "react";
import {Root} from "../../dataCenter/Root";
function ContentItem(props) {
const {icon, name, desc, url, follow} = props.value
const {fetchData, updateIndex} = useContext(Root)
const {icon, name, desc, url, follow, id} = props.value
const jumpUrl = url => {
window.location.href = url
}
const deleteItem = id => {
fetchData('/delete/deleteToolBoxById', {id: id})
.then(() => updateIndex())
}
return (
<div className="content-item">
<div className="content-adminTool">
<img src={setting} alt=""/>
<img src={trash} alt="" onClick={() => deleteItem(id)}/>
</div>
<div className="item-icon" onClick={() => jumpUrl(url)}>
<img src={icon ? icon : defaultIcon} alt={name}/>
</div>
......
......@@ -6,13 +6,45 @@
.content-item{
width: 278px;
height: 157px;
border: 1px solid #B995A1;
border: 2px solid #B995A1;
border-radius: 5px;
padding: 10px;
box-sizing: border-box;
background: $itemBg;
position: relative;
.content-adminTool{
width: 36px;
height: 15px;
position: absolute;
top: 3px;
right: 10px;
line-height: 15px;
display: flex;
justify-content: space-between;
img {
width: 15px;
height: 15px;
cursor: pointer;
}
}
.content-adminTool-close{
//@include test();
width: 30px;
height: 20px;
position: absolute;
top: 10px;
right: 10px;
text-align: center;
line-height: 20px;
font-weight: bold;
font-size: 18px;
z-index: 1;
border: 2px solid #B995A1;
cursor: pointer;
}
.item-icon{
width: 65px;
height: 65px;
......@@ -28,11 +60,11 @@
.item-name{
position: absolute;
height: 30px;
width: 190px;
max-width: 190px;
font-size: 17px;
font-weight: bold;
line-height: 30px;
left: 74px;
left: 78px;
top: 10px;
cursor: pointer;
@include textOverflow();
......@@ -44,6 +76,7 @@
font-size: 12px;
border-top: 2px solid #344857;
padding-top: 3px;
margin-top: 3px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box; /* 将对象作为弹性伸缩盒子模型显示 */
......@@ -53,6 +86,7 @@
}
.item-url{
@include textOverflow();
display: block;
width: 245px;
font-size: 12px;
color: #5F2150;
......@@ -63,7 +97,7 @@
height: 25px;
position: absolute;
top: 40px;
left: 74px;
left: 78px;
line-height: 25px;
font-weight: bold;
font-size: 14px;
......
import './Pop_addToolBox.scss'
import {useContext} from "react";
import {useContext, useRef} from "react";
import {PopContext, Root} from "../../dataCenter/Root";
import {useFormState} from "../../utils/hook";
import closeIcon from '../../static/cancel.png'
function Pop_addToolBox () {
const {fetchData} = useContext(Root)
function Pop_addToolBox() {
const {fetchData, updateIndex} = useContext(Root)
const {hidePop} = useContext(PopContext)
const [input, setInput] = useFormState()
const addToolBox = ()=>{
fetchData('/addToolBox',input)
const PopRef = useRef()
const addToolBox = () => {
fetchData('/add/addToolBox', input)
.then(() => updateIndex())
}
return (
<div className="Pop-container">
<div className="Pop-container"
ref={PopRef}>
<div className="Pop-tool">
<button className="close" onClick={()=> hidePop()}>X</button>
<button className="close" onClick={() => hidePop()}>X</button>
</div>
<h2 className='Pop-title'>新建工具盒</h2>
<div className="formArea">
<div className="item-addToolBox">
<label> 名称:</label> <input type="text" onChange={e => setInput('name',e.target.value)}/>
<div className="input-group ">
<input type="text" onChange={e => setInput('name', e.target.value)} defaultValue={input?.name}
min={1} required/>
<span> 名称</span>
</div>
<div className="item-addToolBox">
<label> 图标:</label> <input type="text" onChange={e => setInput('icon',e.target.value)}/>
<div className="input-group ">
<input type="text" onChange={e => setInput('icon', e.target.value)} defaultValue={input?.icon}
min={1} required/>
<span> 图标</span>
</div>
<div className="item-addToolBox">
<label> 描述:</label> <input type="text" onChange={e => setInput('desc',e.target.value)}/>
<div className="input-group ">
<input type="text" onChange={e => setInput('desc', e.target.value)} defaultValue={input?.desc}
min={1} required/>
<span> 描述</span>
</div>
<div className="item-addToolBox">
<label> 链接:</label> <input type="text" onChange={e => setInput('url',e.target.value)}/>
<div className="input-group ">
<input type="text" onChange={e => setInput('url', e.target.value)} defaultValue={input?.url} min={1}
required/>
<span> 链接</span>
</div>
</div>
<button className='btn-submit-addToolBox'>提交</button>
<div className="Pop-bottom">
<button className='btn-submit-addToolBox' onClick={() => addToolBox()}>提交</button>
</div>
</div>
)
}
......
.Pop-container {
width: 300px;
height: 600px;
@import "../../common/popStyle";
.Pop-container{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(219, 220, 224, 0.7);
border-radius: 5px;
border: 2px solid #DBDCE0;
.Pop-tool{
height: 24px;
background: rgba(0, 0, 0, 0.7);
.close{
width: 23px;
height: 23px;
font-size: 18px;
color: #ffffff;
background: rgba(0, 0, 0,0.9);
}
}
top: 100px;
left: 200px;
}
import {useContext} from "react";
import {PopContext, Root} from "../../dataCenter/Root";
import {useFormState} from "../../utils/hook";
function Pop_addType(props){
const {fetchData, updateIndex} = useContext(Root)
const {hidePop} = useContext(PopContext)
const [input, setInput] = useFormState()
const addType = () => {
fetchData('/add/addType', input)
.then(() => updateIndex())
}
return (
<div className="Pop-container">
<div className="Pop-tool">
<button className="close" onClick={() => hidePop()}>X</button>
</div>
<h2 className='Pop-title'>新建类型</h2>
<div className="formArea">
<div className="input-group ">
<input type="text" onChange={e => setInput('name', e.target.value)} defaultValue={input?.name}
min={1} required/>
<span> 类型名称</span>
</div>
</div>
<div className="Pop-bottom">
<button className='btn-submit-addToolBox' onClick={() => addType()}>提交</button>
</div>
</div>
)
}
export default Pop_addType
@import "../../common/popStyle";
.Pop-container{
position: absolute;
top: 100px;
left: 200px;
}
......@@ -13,7 +13,16 @@ function DataCenter(props) {
const generateUrl = (path, requestData) => {
if (requestData) {
return apiConfig.domain + path + `?${requestData}`
const keyArr = Object.keys(requestData)
const paramsStr = keyArr.map((v, i) => {
if (i === 0) {
return '?' + v + '=' + requestData[v]
} else {
return '&' + v + '=' + requestData[v]
}
}).join('')
console.log('发送请求:', apiConfig.domain + path + paramsStr)
return apiConfig.domain + path + paramsStr
}
return apiConfig.domain + path
}
......@@ -25,13 +34,13 @@ function DataCenter(props) {
* @param requestData
* @returns {Promise<T>}
*/
const fetchData = (path,requestData,dataName) =>
fetch(generateUrl(path,requestData), {credentials: 'include'})
const fetchData = (path, requestData, dataName) =>
fetch(generateUrl(path, requestData), {credentials: 'include'})
.then(res => res.json())
.then(res => {
if (res.success){
if (res.success) {
!!dataName && dispatch(UPDATE_DATA({[dataName]: res.data}))
}else {
} else {
throw res
}
return res
......@@ -41,8 +50,13 @@ function DataCenter(props) {
return e
})
const updateIndex = () => {
fetchData('/query/queryType', {}, 'type')
.then(() => fetchData('/query/queryToolBox', {}, 'toolBox'))
}
return (
<Root.Provider value={{dataCenter, dispatch, fetchData}}>
<Root.Provider value={{dataCenter, dispatch, fetchData, updateIndex}}>
{
props.children
}
......@@ -52,7 +66,7 @@ function DataCenter(props) {
export {
Root,
PopContext
PopContext,
}
export default DataCenter
const UPDATE_DATA = data => ({type: 'UPDATE_DATA', data: {...data}})
export {
UPDATE_DATA,
}
......@@ -4,16 +4,15 @@ import Content from "../component/Content/Content";
import {useContext, useEffect, useState} from "react";
import Pop_addToolBox from "../component/Pop_addToolBox/Pop_addToolBox";
import {PopContext, Root} from "../dataCenter/Root";
import Pop_addType from "../component/Pop_addType/Pop_addType";
function Index() {
const {fetchData} = useContext(Root)
const {updateIndex} = useContext(Root)
const [pop, setPop] = useState('')
console.log(JSON.stringify({name:1,icon:1,desc:1,url:'https://www.baidu.com'}))
const getIndex = () => fetchData('/queryType',{}, 'type')
.then(() => fetchData('/queryToolBox',{}, 'toolBox'))
console.log(JSON.stringify({name: 1, icon: 1, desc: 1, url: 'https://www.baidu.com'}))
useEffect(() => {
getIndex()
updateIndex()
}, [])
return (
......@@ -23,6 +22,7 @@ function Index() {
</div>
<div className="adminTool">
<button className='btn-admin' onClick={() => setPop('addToolBox')}>新建工具盒</button>
<button className='btn-admin' onClick={() => setPop('addType')}>新建类型</button>
</div>
<div className="tool-nav">
<ToolType/>
......@@ -35,6 +35,9 @@ function Index() {
{
pop === 'addToolBox' && <Pop_addToolBox/>
}
{
pop === 'addType' && <Pop_addType/>
}
</PopContext.Provider>
</div>
)
......
<?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="1629861469690" class="icon" viewBox="0 0 1097 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1162"
width="214.2578125" height="200"><defs><style type="text/css"></style></defs><path d="M526.628571 877.860571c59.245714 0 114.541714 22.674286 156.745143 64.219429a446.244571 446.244571 0 0 0 129.170286-74.825143 222.573714 222.573714 0 0 1 22.747429-168.082286 221.622857 221.622857 0 0 1 134.070857-103.936c4.315429-25.380571 6.436571-50.468571 6.436571-74.898285 0-24.356571-2.194286-49.444571-6.436571-74.825143a221.769143 221.769143 0 0 1-134.070857-103.936 222.500571 222.500571 0 0 1-22.674286-168.155429 444.854857 444.854857 0 0 0-129.316572-74.752A221.549714 221.549714 0 0 1 526.628571 162.816c-59.245714 0-114.468571-22.747429-156.672-64.219429A445.074286 445.074286 0 0 0 240.64 173.494857a222.354286 222.354286 0 0 1-22.747429 168.082286 221.622857 221.622857 0 0 1-133.997714 103.862857c-4.388571 25.380571-6.509714 50.468571-6.509714 74.898286 0 24.429714 2.194286 49.517714 6.509714 74.898285a221.622857 221.622857 0 0 1 133.997714 103.862858 222.354286 222.354286 0 0 1 22.747429 168.155428 446.464 446.464 0 0 0 129.243429 74.825143 221.403429 221.403429 0 0 1 156.672-64.219429m-152.502858 144.091429a61.805714 61.805714 0 0 1-20.260571-3.437714h-0.219429a524.141714 524.141714 0 0 1-171.154285-99.108572 62.171429 62.171429 0 0 1-18.651429-64.877714A146.285714 146.285714 0 0 0 150.820571 737.718857a145.334857 145.334857 0 0 0-94.354285-69.632 61.952 61.952 0 0 1-46.957715-48.859428A532.114286 532.114286 0 0 1 0 520.338286c0-32.256 3.218286-65.536 9.508571-98.816a61.952 61.952 0 0 1 46.957715-48.859429 145.334857 145.334857 0 0 0 94.354285-69.632A146.285714 146.285714 0 0 0 163.84 186.221714a62.025143 62.025143 0 0 1 18.724571-64.877714A522.459429 522.459429 0 0 1 353.718857 22.235429a61.952 61.952 0 0 1 65.828572 16.310857c28.086857 30.281143 66.194286 46.957714 107.081142 46.957714 40.96 0 78.994286-16.676571 107.154286-46.957714a61.952 61.952 0 0 1 65.828572-16.237715c63.122286 21.942857 120.685714 55.296 171.154285 98.962286 18.505143 16.091429 25.819429 41.545143 18.651429 64.950857a146.432 146.432 0 0 0 13.092571 116.809143c20.48 35.547429 53.979429 60.342857 94.354286 69.632 23.917714 5.485714 42.349714 24.649143 46.884571 48.859429 6.363429 33.353143 9.508571 66.56 9.508572 98.816 0 32.182857-3.145143 65.536-9.508572 98.889143a61.952 61.952 0 0 1-46.957714 48.859428 145.334857 145.334857 0 0 0-94.354286 69.632 146.505143 146.505143 0 0 0-13.019428 116.809143 62.025143 62.025143 0 0 1-18.651429 64.877714 524.141714 524.141714 0 0 1-171.154285 99.108572h-0.146286a62.171429 62.171429 0 0 1-65.682286-16.384 144.969143 144.969143 0 0 0-107.154286-46.884572c-40.96 0-78.994286 16.603429-107.154285 46.957715a62.171429 62.171429 0 0 1-45.348572 19.748571" fill="#000000" p-id="1163"></path><path d="M526.409143 393.947429a126.537143 126.537143 0 0 0-126.464 126.464 126.537143 126.537143 0 0 0 126.464 126.390857 126.537143 126.537143 0 0 0 126.390857-126.390857 126.537143 126.537143 0 0 0-126.390857-126.464m0 327.094857a200.850286 200.850286 0 0 1-200.630857-200.630857 200.850286 200.850286 0 0 1 200.630857-200.630858A200.850286 200.850286 0 0 1 727.04 520.411429a200.850286 200.850286 0 0 1-200.630857 200.630857" fill="#000000" p-id="1164"></path></svg>
<?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="1629861474867" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1316"
width="200" height="200"><defs><style type="text/css"></style></defs><path d="M666.686094 949.472752H355.997429L217.694165 223.362331h587.295193l-138.230127 726.110421zM316.064281 74.45411h390.55496l21.283052 74.454111H294.78123l21.209913-74.454111z m632.786801 74.454111H805.281908L770.541533 27.060924a37.227055 37.227055 0 0 0-35.83744-27.060924H287.97943a37.227055 37.227055 0 0 0-35.83744 27.060924l-34.740376 121.920434H73.832441a37.300193 37.300193 0 0 0 0 74.454111h68.017998l146.714092 770.285551a37.300193 37.300193 0 0 0 36.568817 30.27898h372.343689a37.300193 37.300193 0 0 0 36.568817-30.27898l146.714092-770.285551h68.017998a37.300193 37.300193 0 0 0 0-74.454111z" fill="#000000" p-id="1317"></path><path d="M511.268624 837.791586c10.312406 0 18.650096-8.33769 18.650096-18.650096V297.889579a18.650096 18.650096 0 0 0-37.227055 0V819.14149c0 10.239269 8.33769 18.650096 18.650096 18.650096M436.814513 837.791586l1.389615-0.073137a18.650096 18.650096 0 0 0 17.260482-19.893437l-37.300193-521.25191a18.796372 18.796372 0 0 0-19.820299-17.260481 18.650096 18.650096 0 0 0-17.260481 19.893436l37.227055 521.25191c0.731376 9.800443 8.849654 17.333619 18.503821 17.333619M584.406257 837.718449a18.650096 18.650096 0 0 0 19.893436-17.260482l37.300193-521.25191a18.650096 18.650096 0 0 0-17.260482-19.893436 18.796372 18.796372 0 0 0-19.893436 17.260481l-37.227055 521.25191c-0.731376 10.239269 7.021213 19.16206 17.260481 19.893437" fill="#000000" p-id="1318"></path></svg>
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