Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
bkunyun
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
bkunyun
Commits
1694936d
Commit
1694936d
authored
Jun 15, 2022
by
wuyongsheng
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat-20220608-projectdata' into 'release'
Feat 20220608 projectdata See merge request
sunyihao/bkunyun!37
parents
e8146cce
500f7e4e
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
382 additions
and
156 deletions
+382
-156
raysyncApi.ts
src/api/fileserver/raysyncApi.ts
+1
-0
uploadIcon.svg
src/assets/img/uploadIcon.svg
+32
-0
useMyRouter.ts
src/components/MyRouter/useMyRouter.ts
+8
-1
MyDialog.tsx
src/components/mui/MyDialog.tsx
+5
-1
currentProject.ts
src/store/modules/currentProject.ts
+1
-0
fileList.ts
src/store/modules/fileList.ts
+8
-10
tusUpload.js
src/utils/Upload/tusUpload.js
+14
-55
util.ts
src/utils/util.ts
+34
-1
index.module.css
src/views/ConsoleLayout/components/FileItem/index.module.css
+20
-0
index.tsx
src/views/ConsoleLayout/components/FileItem/index.tsx
+65
-6
index.tsx
src/views/ConsoleLayout/index.tsx
+11
-4
index.module.css
src/views/Project/ProjectData/UpLoaderFile/index.module.css
+2
-2
index.tsx
src/views/Project/ProjectData/UpLoaderFile/index.tsx
+66
-27
index.tsx
src/views/Project/ProjectData/index.tsx
+46
-27
index.tsx
src/views/Project/ProjectSetting/BaseInfo/index.tsx
+11
-1
AddMember.tsx
...ct/ProjectSetting/ProjectMembers/components/AddMember.tsx
+24
-12
RemoveItem.tsx
...t/ProjectSetting/ProjectMembers/components/RemoveItem.tsx
+1
-5
index.tsx
src/views/Project/ProjectSetting/ProjectMembers/index.tsx
+2
-2
index.tsx
src/views/Project/components/AddProject/index.tsx
+16
-0
index.tsx
src/views/Project/components/CurrentProject/index.tsx
+8
-1
project.ts
src/views/Project/project.ts
+7
-1
No files found.
src/api/fileserver/raysyncApi.ts
View file @
1694936d
...
@@ -116,6 +116,7 @@ export {
...
@@ -116,6 +116,7 @@ export {
getType
,
getType
,
};
};
// mock 数据
// const raysyncAddr = {
// const raysyncAddr = {
// bandwidth: null
// bandwidth: null
// capacity: 10485760
// capacity: 10485760
...
...
src/assets/img/uploadIcon.svg
0 → 100644
View file @
1694936d
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"18px"
height=
"16px"
viewBox=
"0 0 18 16"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<title>
1.Base基础/Icon图标/文件传输
</title>
<defs>
<filter
color-interpolation-filters=
"auto"
id=
"filter-1"
>
<feColorMatrix
in=
"SourceGraphic"
type=
"matrix"
values=
"0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"
></feColorMatrix>
</filter>
<filter
color-interpolation-filters=
"auto"
id=
"filter-2"
>
<feColorMatrix
in=
"SourceGraphic"
type=
"matrix"
values=
"0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"
></feColorMatrix>
</filter>
</defs>
<g
id=
"上线UI"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"项目数据-长路径"
transform=
"translate(-1324.000000, -136.000000)"
>
<g
id=
"编组-10"
transform=
"translate(1317.000000, 128.000000)"
>
<g
id=
"文件传输"
transform=
"translate(7.000000, 7.000000)"
filter=
"url(#filter-1)"
>
<g>
<rect
id=
"矩形备份-5"
x=
"0"
y=
"0"
width=
"18"
height=
"18"
></rect>
<g
filter=
"url(#filter-2)"
>
<g
transform=
"translate(0.000000, 1.687500)"
>
<path
d=
"M5.95624614,0.9 L7.0470055,1.84033454 C7.43885553,2.2205386 7.96337743,2.43318258 8.50936421,2.43318258 L8.50936421,2.43318258 L16.8,2.43318258 L17.1,13.425 L1.2,13.725 L0.9,1.2 L5.95624614,0.9 Z"
id=
"路径-4"
stroke=
"#7C878E"
stroke-width=
"1.8"
></path>
<polygon
id=
"路径-5"
fill=
"#7C878E"
points=
"9.26587781 3.28436599 1.47245698 3.28436599 1.47245698 1.2526684 6.01231277 1.2526684"
></polygon>
<polygon
id=
"路径-6"
fill=
"#7C878E"
fill-rule=
"nonzero"
points=
"8.05145975 5.6167684 8.05145975 10.8168243 5.59717839 10.8168243 5.59717839 9.06182432 6.2508 9.0612484 6.25145975 5.6167684"
></polygon>
<polygon
id=
"路径-6备份"
fill=
"#7C878E"
fill-rule=
"nonzero"
transform=
"translate(11.062078, 8.216796) scale(-1, -1) translate(-11.062078, -8.216796) "
points=
"12.2726957 5.6167684 12.2726957 10.81608 9.85203814 10.8168243 9.85145975 9.06182437 10.472057 9.0612484 10.4726957 5.6167684"
></polygon>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
src/components/MyRouter/useMyRouter.ts
View file @
1694936d
...
@@ -8,7 +8,10 @@ import NotFound from "@/views/404";
...
@@ -8,7 +8,10 @@ import NotFound from "@/views/404";
import
useMyRequest
from
"@/hooks/useMyRequest"
;
import
useMyRequest
from
"@/hooks/useMyRequest"
;
import
{
useEffect
}
from
"react"
;
import
{
useEffect
}
from
"react"
;
import
{
menu
}
from
"@/api/routes_api"
;
import
{
menu
}
from
"@/api/routes_api"
;
import
{
setFileServerEndPointLocalStorage
}
from
"@/views/Project/project"
;
import
{
setFileServerEndPointLocalStorage
,
getFiletokenAccordingToId
,
}
from
"@/views/Project/project"
;
const
useMyRouter
=
()
=>
{
const
useMyRouter
=
()
=>
{
const
{
permissionStore
,
menuStore
,
currentProjectStore
}
=
useStores
();
const
{
permissionStore
,
menuStore
,
currentProjectStore
}
=
useStores
();
...
@@ -53,6 +56,10 @@ const useMyRouter = () => {
...
@@ -53,6 +56,10 @@ const useMyRouter = () => {
currentProjectStore
.
setProjectList
(
list
);
currentProjectStore
.
setProjectList
(
list
);
currentProjectStore
.
changeProject
(
list
[
0
]);
currentProjectStore
.
changeProject
(
list
[
0
]);
setFileServerEndPointLocalStorage
(
list
[
0
].
zoneId
);
setFileServerEndPointLocalStorage
(
list
[
0
].
zoneId
);
getFiletokenAccordingToId
(
list
[
0
].
id
).
then
((
res
)
=>
{
list
[
0
].
filetoken
=
res
;
currentProjectStore
.
changeProject
(
list
[
0
]);
});
}
}
}
}
...
...
src/components/mui/MyDialog.tsx
View file @
1694936d
...
@@ -26,7 +26,11 @@ const MyDialog = (props: any) => {
...
@@ -26,7 +26,11 @@ const MyDialog = (props: any) => {
setOpen
(
true
);
setOpen
(
true
);
};
};
const
handleClose
=
()
=>
{
const
handleClose
=
(
event
:
any
=
{},
reason
:
any
=
"other"
)
=>
{
// 点击弹窗外不关闭弹窗
if
(
reason
===
"backdropClick"
)
{
return
;
}
setOpen
(
false
);
setOpen
(
false
);
};
};
...
...
src/store/modules/currentProject.ts
View file @
1694936d
...
@@ -4,6 +4,7 @@ type projectInfo = {
...
@@ -4,6 +4,7 @@ type projectInfo = {
name
?:
string
;
name
?:
string
;
desc
?:
string
;
desc
?:
string
;
projectRole
?:
string
;
projectRole
?:
string
;
filetoken
?:
string
;
};
};
type
productInfo
=
{
type
productInfo
=
{
...
...
src/store/modules/fileList.ts
View file @
1694936d
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 17:00:19
* @Date: 2022-06-13 17:00:19
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-1
4 21:47:28
* @LastEditTime: 2022-06-1
5 15:24:44
* @FilePath: /bkunyun/src/store/modules/upload.ts
* @FilePath: /bkunyun/src/store/modules/upload.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
...
@@ -12,6 +12,7 @@ import { makeAutoObservable, observable, action } from "mobx";
...
@@ -12,6 +12,7 @@ import { makeAutoObservable, observable, action } from "mobx";
interface
IUploadInfo
{
interface
IUploadInfo
{
id
:
string
,
id
:
string
,
open
:
boolean
,
open
:
boolean
,
file
:
File
,
list
:
any
,
list
:
any
,
isPermanence
:
boolean
,
isPermanence
:
boolean
,
}
}
...
@@ -34,27 +35,24 @@ class FileList {
...
@@ -34,27 +35,24 @@ class FileList {
newFileList
:
IUploadInfo
[]
=
[];
newFileList
:
IUploadInfo
[]
=
[];
/** 设置最新需要上传的文件列表 */
/** 设置最新需要上传的文件列表 */
setNewFileList
(
val
:
IUploadInfo
[])
{
setNewFileList
=
(
val
:
IUploadInfo
[])
=>
{
this
.
fileList
=
this
.
fileList
.
concat
(
val
)
this
.
fileList
=
this
.
fileList
.
concat
(
val
)
this
.
newFileList
=
val
this
.
newFileList
=
val
}
}
/** 设置文件上传信息 */
/** 设置文件上传信息 */
setUploadInfo
(
id
:
string
,
val
:
IUploadInfo
)
{
setUploadInfo
=
(
id
:
string
,
val
:
IUploadInfo
)
=>
{
console
.
log
(
val
,
id
,
'2
2222'
)
console
.
log
(
id
,
val
,
'
2222'
)
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
if
(
item
.
id
===
id
){
if
(
item
.
id
===
id
){
console
.
log
(
'3333'
,
item
)
return
val
return
val
}
return
item
}
return
item
})
})
this
.
fileList
=
newFileList
this
.
fileList
=
newFileList
}
}
setUploadInfoOpen
(
id
:
string
,
val
:
boolean
)
{
setUploadInfoOpen
=
(
id
:
string
,
val
:
boolean
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
if
(
item
.
id
===
id
){
if
(
item
.
id
===
id
){
return
{...
item
,
open
:
val
};
return
{...
item
,
open
:
val
};
...
@@ -64,7 +62,7 @@ class FileList {
...
@@ -64,7 +62,7 @@ class FileList {
this
.
fileList
=
newFileList
this
.
fileList
=
newFileList
}
}
setUploadInfoList
(
id
:
string
,
val
:
any
)
{
setUploadInfoList
=
(
id
:
string
,
val
:
any
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
if
(
item
.
id
===
id
){
if
(
item
.
id
===
id
){
return
{...
item
,
list
:
val
}
return
{...
item
,
list
:
val
}
...
@@ -73,7 +71,7 @@ class FileList {
...
@@ -73,7 +71,7 @@ class FileList {
this
.
fileList
=
newFileList
this
.
fileList
=
newFileList
}
}
setUploadInfoIsPermanence
(
id
:
string
,
val
:
boolean
)
{
setUploadInfoIsPermanence
=
(
id
:
string
,
val
:
boolean
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
const
newFileList
=
this
.
fileList
?.
map
((
item
)
=>
{
if
(
item
.
id
===
id
){
if
(
item
.
id
===
id
){
return
{...
item
,
isPermanence
:
val
}
return
{...
item
,
isPermanence
:
val
}
...
...
src/utils/Upload/tusUpload.js
View file @
1694936d
...
@@ -8,7 +8,6 @@ import {
...
@@ -8,7 +8,6 @@ import {
import
{
getDataFileToken
}
from
"@/api/project_api"
;
import
{
getDataFileToken
}
from
"@/api/project_api"
;
import
useMyRequest
from
"@/hooks/useMyRequest"
;
import
useMyRequest
from
"@/hooks/useMyRequest"
;
import
{
getTokenInfo
}
from
"@/utils/util"
;
import
{
getTokenInfo
}
from
"@/utils/util"
;
import
ConsoleLayout
from
"@/views/ConsoleLayout"
;
const
UseTusUpload
=
(
props
)
=>
{
const
UseTusUpload
=
(
props
)
=>
{
const
{
fileListStore
:
uploadInfoStore
,
currentProjectStore
}
=
props
;
const
{
fileListStore
:
uploadInfoStore
,
currentProjectStore
}
=
props
;
...
@@ -31,16 +30,15 @@ const UseTusUpload = (props) => {
...
@@ -31,16 +30,15 @@ const UseTusUpload = (props) => {
});
});
},
[]);
},
[]);
const
{
fileList
}
=
uploadInfoStore
;
const
uploadFile
=
(
item
,
file
,
url
,
filepath
,
callBack
)
=>
{
const
uploadFile
=
(
item
,
file
,
url
,
filepath
,
callBack
)
=>
{
for
(
let
i
in
localStorage
)
{
if
(
i
.
indexOf
(
"tus::tus-br"
)
>
-
1
)
{
localStorage
.
removeItem
(
i
);
}
}
uploadInfoStore
?.
setUploadInfoIsPermanence
(
item
.
id
,
false
);
uploadInfoStore
?.
setUploadInfoIsPermanence
(
item
.
id
,
false
);
console
.
log
(
fileList
);
if
(
!
verifyLettersNumbersCertainChars4
(
file
.
name
))
{
if
(
!
verifyLettersNumbersCertainChars4
(
file
.
name
))
{
let
json1
=
uploadInfoStore
?.
uploadInfo
?.
list
.
concat
({
console
.
log
(
222
);
let
json1
=
item
?.
list
.
concat
({
name
:
file
.
name
,
name
:
file
.
name
,
bytesUploaded
:
0
,
bytesUploaded
:
0
,
bytesTotal
:
0
,
bytesTotal
:
0
,
...
@@ -56,6 +54,7 @@ const UseTusUpload = (props) => {
...
@@ -56,6 +54,7 @@ const UseTusUpload = (props) => {
"上传失败,文件或文件夹的命名长度不超过127字节,不支持特殊符号、空格。"
,
"上传失败,文件或文件夹的命名长度不超过127字节,不支持特殊符号、空格。"
,
});
});
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
...
item
,
open
:
true
,
open
:
true
,
list
:
json1
,
list
:
json1
,
isPermanence
:
false
,
isPermanence
:
false
,
...
@@ -84,10 +83,7 @@ const UseTusUpload = (props) => {
...
@@ -84,10 +83,7 @@ const UseTusUpload = (props) => {
},
},
onProgress
:
function
(
bytesUploaded
,
bytesTotal
,
a
)
{
onProgress
:
function
(
bytesUploaded
,
bytesTotal
,
a
)
{
var
percentage
=
((
bytesUploaded
/
bytesTotal
)
*
100
).
toFixed
(
2
);
var
percentage
=
((
bytesUploaded
/
bytesTotal
)
*
100
).
toFixed
(
2
);
let
fliterJson
=
item
.
list
?.
filter
((
item
)
=>
item
.
id
===
timeId
);
const
json
=
item
.
list
.
concat
({
let
json
=
[];
if
(
fliterJson
.
length
===
0
)
{
json
=
item
.
list
.
concat
({
name
:
upload
.
file
.
name
,
name
:
upload
.
file
.
name
,
bytesUploaded
:
bytesUploaded
,
bytesUploaded
:
bytesUploaded
,
bytesTotal
:
bytesTotal
,
bytesTotal
:
bytesTotal
,
...
@@ -100,44 +96,17 @@ const UseTusUpload = (props) => {
...
@@ -100,44 +96,17 @@ const UseTusUpload = (props) => {
upload
,
upload
,
dir
:
"/home/cloudam/"
,
dir
:
"/home/cloudam/"
,
});
});
console
.
log
(
item
,
"0111111"
);
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
...
item
,
open
:
true
,
open
:
true
,
list
:
json
,
list
:
json
||
[],
isPermanence
:
uploadInfoStore
?.
uploadInfo
?.
isPermanence
,
});
}
else
{
let
a
=
item
.
list
;
let
time
=
new
Date
().
getTime
();
a
.
map
((
element
)
=>
{
if
(
element
.
id
===
timeId
)
{
element
[
"bytesUploaded"
]
=
bytesUploaded
;
element
[
"bytesTotal"
]
=
bytesTotal
;
element
[
"percentage"
]
=
percentage
;
element
[
"bytesUploaded2"
]
=
parseInt
((
parseInt
(
time
)
-
parseInt
(
element
.
endTime
))
/
1000
)
>=
2
?
bytesUploaded
:
element
[
"bytesUploaded2"
];
element
[
"endTime"
]
=
parseInt
((
parseInt
(
time
)
-
parseInt
(
element
.
endTime
))
/
1000
)
>=
2
?
time
:
element
[
"endTime"
];
}
});
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
open
:
true
,
list
:
a
.
concat
([]),
isPermanence
:
item
.
isPermanence
,
isPermanence
:
item
.
isPermanence
,
});
});
}
},
},
onSuccess
:
function
()
{
onSuccess
:
function
()
{
let
fliterJson
=
item
.
list
.
filter
((
item
)
=>
item
.
id
===
timeId
);
console
.
log
(
upload
.
file
,
"9999999"
);
if
(
fliterJson
.
length
===
0
&&
upload
.
file
[
"size"
]
===
0
)
{
console
.
log
(
"000011111"
);
let
json
=
[];
let
json
=
[];
json
=
item
.
list
.
concat
({
json
=
item
.
list
.
concat
({
name
:
upload
.
file
.
name
,
name
:
upload
.
file
.
name
,
bytesUploaded
:
0
,
bytesUploaded
:
0
,
...
@@ -150,24 +119,14 @@ const UseTusUpload = (props) => {
...
@@ -150,24 +119,14 @@ const UseTusUpload = (props) => {
statusMsg
:
"上传成功"
,
statusMsg
:
"上传成功"
,
upload
,
upload
,
});
});
console
.
log
(
json
,
item
.
list
,
"0222222"
);
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
...
item
,
open
:
true
,
open
:
true
,
list
:
json
,
list
:
json
,
isPermanence
:
item
.
isPermanence
,
isPermanence
:
item
.
isPermanence
,
});
});
}
else
{
console
.
log
(
item
.
list
,
"000022222"
);
item
.
list
.
map
((
item
)
=>
{
if
(
item
.
id
===
timeId
)
{
item
[
"statusMsg"
]
=
"上传成功"
;
}
});
uploadInfoStore
?.
setUploadInfo
(
item
.
id
,
{
open
:
true
,
list
:
item
.
list
,
isPermanence
:
item
.
isPermanence
,
});
}
callBack
&&
callBack
(
upload
,
filepath
);
callBack
&&
callBack
(
upload
,
filepath
);
},
},
});
});
...
...
src/utils/util.ts
View file @
1694936d
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-07 18:37:53
* @Date: 2022-06-07 18:37:53
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-1
4 17:21:52
* @LastEditTime: 2022-06-1
5 17:49:27
* @FilePath: /bkunyun/src/utils/util.ts
* @FilePath: /bkunyun/src/utils/util.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
...
@@ -29,6 +29,22 @@ export const uuid = () => {
...
@@ -29,6 +29,22 @@ export const uuid = () => {
return
pwd
;
return
pwd
;
};
};
/** 格式化时间 xx小时xx分钟xx秒
* params: item: 毫秒的时间戳
*/
export
const
formatTime
=
(
time
:
number
)
=>
{
const
newTime
=
Math
.
floor
(
time
/
1000
)
;
const
hours
=
Math
.
floor
(
newTime
/
3600
);
const
minutes
=
Math
.
floor
((
newTime
%
3600
)
/
60
);
const
seconds
=
newTime
%
60
;
const
hoursString
=
hours
?
`
${
hours
}
小时`
:
''
;
const
minutesString
=
minutes
?
`
${
minutes
}
分钟`
:
''
;
const
secondsString
=
seconds
?
`
${
seconds
}
秒`
:
''
;
return
`
${
hoursString
}${
minutesString
}${
secondsString
}
`
;
};
// 获取用户信息
// 获取用户信息
export
const
getUserInfo
=
()
=>
{
export
const
getUserInfo
=
()
=>
{
let
val
:
any
;
let
val
:
any
;
...
@@ -60,3 +76,20 @@ export const checkIsNumberLetterChinese = (string: string) => {
...
@@ -60,3 +76,20 @@ export const checkIsNumberLetterChinese = (string: string) => {
export
const
getMbfromB
=
(
b
:
number
)
=>
{
export
const
getMbfromB
=
(
b
:
number
)
=>
{
return
Math
.
floor
(
b
/
1048576
);
return
Math
.
floor
(
b
/
1048576
);
};
};
// 内存单位转换
export
const
storageUnitFromB
=
(
b
:
number
)
=>
{
if
(
b
<=
0
)
{
return
"0B"
;
}
else
if
(
b
<
1024
)
{
return
`
${
b
}
B`
;
}
else
if
(
b
<
1024
*
1024
)
{
return
`
${(
b
/
1024
).
toFixed
(
2
)}
KB`
;
}
else
if
(
b
<
1024
*
1024
*
1024
)
{
return
`
${(
b
/
(
1024
*
1024
)).
toFixed
(
2
)}
MB`
;
}
else
if
(
b
<
1024
*
1024
*
1024
*
1024
)
{
return
`
${(
b
/
(
1024
*
1024
*
1024
)).
toFixed
(
2
)}
G`
;
}
else
{
return
`
${(
b
/
(
1024
*
1024
*
1024
*
1024
)).
toFixed
(
2
)}
t`
;
}
};
src/views/ConsoleLayout/components/FileItem/index.module.css
0 → 100644
View file @
1694936d
.itemBox
{
height
:
50px
;
padding
:
16px
0
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
border-bottom
:
1px
solid
#f0f2f5
;
}
.rightBox
{
font-size
:
12px
;
color
:
#1370ff
;
}
.leftBox
{
display
:
flex
;
}
.span
{
color
:
#8a9099
;
font-size
:
12px
;
}
src/views/ConsoleLayout/components/FileItem/index.tsx
View file @
1694936d
import
{
observer
}
from
"mobx-react-lite"
;
import
{
toJS
}
from
"mobx"
;
// import { any } from "@/store/modules/fileList";
// toJS(currentProjectStore.currentProjectInfo.id);
import
{
LinearProgress
}
from
"@mui/material"
;
import
styles
from
"./index.module.css"
;
import
{
useMemo
}
from
"react"
;
import
{
formatTime
,
storageUnitFromB
}
from
"@/utils/util"
;
/*
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-11 15:46:42
* @Date: 2022-06-11 15:46:42
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-1
4 21:35:09
* @LastEditTime: 2022-06-1
5 18:03:31
* @FilePath: /bkunyun/src/views/ConsoleLayout/components/FileItem/index.tsx
* @FilePath: /bkunyun/src/views/ConsoleLayout/components/FileItem/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
...
@@ -16,8 +20,63 @@ interface IProps {
...
@@ -16,8 +20,63 @@ interface IProps {
}
}
const
FileItem
=
(
props
:
IProps
)
=>
{
const
FileItem
=
(
props
:
IProps
)
=>
{
const
{
fileItemInfo
}
=
props
;
const
{
fileItemInfo
}
=
props
;
console
.
log
(
fileItemInfo
,
2222
);
const
itemInfo
=
toJS
(
fileItemInfo
);
return
<
div
>
dd
</
div
>;
const
lastInfo
=
itemInfo
?.
list
[
itemInfo
.
list
?.
length
-
1
];
const
firstInfo
=
itemInfo
?.
list
[
0
];
const
lastMsg
=
lastInfo
?.
statusMsg
;
const
TimeText
=
useMemo
(()
=>
{
const
val
=
lastInfo
.
endTime
-
firstInfo
.
startTime
;
return
formatTime
(
val
);
},
[
firstInfo
.
startTime
,
lastInfo
.
endTime
]);
const
text
=
useMemo
(()
=>
{
let
result
=
""
;
if
(
lastMsg
===
"上传失败"
)
{
result
=
"重新上传"
;
}
if
(
lastMsg
===
"正在上传"
)
{
result
=
"暂停"
;
}
if
(
lastMsg
===
"上传成功"
)
{
result
=
"查看文件"
;
}
return
result
;
},
[
itemInfo
?.
list
,
lastMsg
]);
return
(
<
div
className=
{
styles
.
itemBox
}
>
<
div
className=
{
styles
.
leftBox
}
>
<
img
/>
<
div
>
<
div
>
<
b
style=
{
{
fontSize
:
14
}
}
>
{
firstInfo
?.
name
||
""
}
</
b
>
{
lastMsg
===
"上传失败"
?
(
<
span
className=
{
styles
.
span
}
style=
{
{
marginLeft
:
16
,
color
:
"#FF4E4E"
}
}
>
{
`(${lastMsg})`
}
</
span
>
)
:
(
<
span
className=
{
styles
.
span
}
style=
{
{
marginLeft
:
16
}
}
>
{
TimeText
}
</
span
>
)
}
</
div
>
<
LinearProgress
sx=
{
{
width
:
300
,
borderRadius
:
2
,
margin
:
"2px 0"
,
color
:
"red"
}
}
variant=
"determinate"
value=
{
50
}
/>
<
div
>
<
span
className=
{
styles
.
span
}
>
{
`700MB/${storageUnitFromB(
500000
)}`
}
</
span
>
</
div
>
</
div
>
</
div
>
<
div
className=
{
styles
.
rightBox
}
>
{
text
}
</
div
>
</
div
>
);
};
};
export
default
FileItem
;
export
default
FileItem
;
src/views/ConsoleLayout/index.tsx
View file @
1694936d
...
@@ -7,6 +7,7 @@ import Add from "@mui/icons-material/Add";
...
@@ -7,6 +7,7 @@ import Add from "@mui/icons-material/Add";
import
Avatar
from
"@mui/material/Avatar"
;
import
Avatar
from
"@mui/material/Avatar"
;
import
{
Box
,
Menu
,
MenuItem
}
from
"@mui/material"
;
import
{
Box
,
Menu
,
MenuItem
}
from
"@mui/material"
;
import
uploadIcon
from
"@/assets/img/uploadIcon.svg"
;
import
globalText
from
"@/utils/globalText_CN"
;
import
globalText
from
"@/utils/globalText_CN"
;
import
useIndex
from
"./useIndex"
;
import
useIndex
from
"./useIndex"
;
import
{
useStores
}
from
"@/store/index"
;
import
{
useStores
}
from
"@/store/index"
;
...
@@ -18,7 +19,7 @@ import TranSferList from "./components/TransferList";
...
@@ -18,7 +19,7 @@ import TranSferList from "./components/TransferList";
import
style
from
"./index.module.css"
;
import
style
from
"./index.module.css"
;
import
useGlobalStore
from
"@/hooks/useGlobalStore"
;
import
useGlobalStore
from
"@/hooks/useGlobalStore"
;
import
{
toJS
}
from
"mobx"
;
import
{
toJS
}
from
"mobx"
;
import
{
urlToken
}
from
"@/api/fileserver/raysyncApi"
;
import
{
APIOPTION
,
urlToken
}
from
"@/api/fileserver/raysyncApi"
;
import
UseTusUpload
from
"@/utils/Upload/tusUpload"
;
import
UseTusUpload
from
"@/utils/Upload/tusUpload"
;
import
useMyRequest
from
"@/hooks/useMyRequest"
;
import
useMyRequest
from
"@/hooks/useMyRequest"
;
import
{
getDataFileToken
}
from
"@/api/project_api"
;
import
{
getDataFileToken
}
from
"@/api/project_api"
;
...
@@ -54,7 +55,8 @@ const ConsoleLayout = observer(() => {
...
@@ -54,7 +55,8 @@ const ConsoleLayout = observer(() => {
const
{
run
:
getDataFileTokenRun
}
=
useMyRequest
(
getDataFileToken
,
{
const
{
run
:
getDataFileTokenRun
}
=
useMyRequest
(
getDataFileToken
,
{
onSuccess
:
(
res
:
any
)
=>
{
onSuccess
:
(
res
:
any
)
=>
{
let
url
=
let
url
=
"https://fileserver.cloudam.cn/parallelupload/"
+
APIOPTION
()
+
"/parallelupload/"
+
urlToken
(
urlToken
(
res
?.
data
||
""
,
res
?.
data
||
""
,
currentProjectStore
?.
currentProjectInfo
?.
id
as
string
currentProjectStore
?.
currentProjectInfo
?.
id
as
string
...
@@ -62,7 +64,7 @@ const ConsoleLayout = observer(() => {
...
@@ -62,7 +64,7 @@ const ConsoleLayout = observer(() => {
fileList
?.
newFileList
?.
forEach
((
item
:
any
)
=>
{
fileList
?.
newFileList
?.
forEach
((
item
:
any
)
=>
{
uploadFile
(
uploadFile
(
item
,
item
,
item
?.
list
,
item
?.
file
,
url
,
url
,
"/"
,
"/"
,
(
upload
:
any
,
filepath
:
string
)
=>
console
.
log
(
upload
,
filepath
,
1111
)
(
upload
:
any
,
filepath
:
string
)
=>
console
.
log
(
upload
,
filepath
,
1111
)
...
@@ -73,6 +75,7 @@ const ConsoleLayout = observer(() => {
...
@@ -73,6 +75,7 @@ const ConsoleLayout = observer(() => {
useDeepEffect
(()
=>
{
useDeepEffect
(()
=>
{
if
(
fileList
?.
newFileList
?.
length
)
{
if
(
fileList
?.
newFileList
?.
length
)
{
console
.
log
(
111
,
222
);
getDataFileTokenRun
({
getDataFileTokenRun
({
id
:
currentProjectStore
?.
currentProjectInfo
.
id
||
""
,
id
:
currentProjectStore
?.
currentProjectInfo
.
id
||
""
,
});
});
...
@@ -148,7 +151,11 @@ const ConsoleLayout = observer(() => {
...
@@ -148,7 +151,11 @@ const ConsoleLayout = observer(() => {
}
}
}
}
>
>
<
Box
className=
{
style
.
topRightItem
}
>
<
Box
className=
{
style
.
topRightItem
}
>
<
Add
/>
<
img
src=
{
uploadIcon
}
alt=
""
style=
{
{
verticalAlign
:
"middle"
}
}
/>
</
Box
>
</
Box
>
</
MyPopover
>
</
MyPopover
>
<
Box
className=
{
style
.
topRightItem
}
>
<
Box
className=
{
style
.
topRightItem
}
>
...
...
src/views/Project/ProjectData/UpLoaderFile/index.module.css
View file @
1694936d
...
@@ -45,10 +45,10 @@
...
@@ -45,10 +45,10 @@
box-sizing
:
border-box
;
box-sizing
:
border-box
;
position
:
relative
;
position
:
relative
;
}
}
.tableBox
{
/*
.tableBox {
height: 300px;
height: 300px;
overflow: scroll;
overflow: scroll;
}
}
*/
.fileIconBox
{
.fileIconBox
{
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
...
...
src/views/Project/ProjectData/UpLoaderFile/index.tsx
View file @
1694936d
import
React
,
{
useState
,
useImperativeHandle
,
useCallback
}
from
"react"
;
import
React
,
{
useState
,
useImperativeHandle
,
useCallback
,
useMemo
,
}
from
"react"
;
import
style
from
"./index.module.css"
;
import
style
from
"./index.module.css"
;
import
MyDialog
from
"@/components/mui/MyDialog"
;
import
MyDialog
from
"@/components/mui/MyDialog"
;
...
@@ -11,7 +16,7 @@ import fileIcon from "@/assets/project/fileIcon.svg";
...
@@ -11,7 +16,7 @@ import fileIcon from "@/assets/project/fileIcon.svg";
import
noFile
from
"@/assets/project/noFile.svg"
;
import
noFile
from
"@/assets/project/noFile.svg"
;
import
uploaderIcon
from
"@/assets/project/uploaderIcon.svg"
;
import
uploaderIcon
from
"@/assets/project/uploaderIcon.svg"
;
import
classnames
from
"classnames"
;
import
classnames
from
"classnames"
;
import
{
getMbf
romB
}
from
"@/utils/util"
;
import
{
storageUnitF
romB
}
from
"@/utils/util"
;
import
{
observer
}
from
"mobx-react"
;
import
{
observer
}
from
"mobx-react"
;
import
{
useStores
}
from
"@/store"
;
import
{
useStores
}
from
"@/store"
;
import
{
toJS
}
from
"mobx"
;
import
{
toJS
}
from
"mobx"
;
...
@@ -23,34 +28,68 @@ const UpLoaderFile = observer((props: any) => {
...
@@ -23,34 +28,68 @@ const UpLoaderFile = observer((props: any) => {
// list 是项目数据table的数据
// list 是项目数据table的数据
const
{
path
,
list
}
=
props
;
const
{
path
,
list
}
=
props
;
// 集合当前路径下的文件、文件夹、数据集 和已选择要上传的文件列表
const
nowNameList
=
useMemo
(()
=>
{
return
[...
list
,
...
fileList
];
},
[
list
,
fileList
]);
const
onDrop
=
useCallback
(
const
onDrop
=
useCallback
(
(
acceptedFiles
:
any
)
=>
{
(
acceptedFiles
:
any
)
=>
{
// 判断是否有文件名重复
// 获取重复的项目文件列表和要上传(名称不重复就上传)的文件
const
fileListRepeatName
=
getRepeatName
(
fileList
,
acceptedFiles
);
const
getRepeatFileAndGetUploderFileList
=
(
const
listRepeatName
=
getRepeatName
(
list
,
acceptedFiles
);
acceptedFiles
:
Array
<
any
>
if
(
fileListRepeatName
||
listRepeatName
)
{
)
=>
{
message
.
error
(
`
${
fileListRepeatName
||
listRepeatName
}
文件已存在`
);
let
repeatFileList
:
any
=
[];
return
;
let
uploderFileList
:
any
=
[];
acceptedFiles
.
forEach
((
fItem
:
any
,
index
:
number
)
=>
{
if
(
nowNameList
.
some
((
nItem
:
any
)
=>
{
return
nItem
.
name
===
fItem
.
name
;
})
)
{
repeatFileList
.
push
(
acceptedFiles
[
index
]);
}
else
{
uploderFileList
.
push
(
acceptedFiles
[
index
]);
}
});
return
{
repeatFileList
,
uploderFileList
,
};
};
const
repeatAndUploaderFileList
=
getRepeatFileAndGetUploderFileList
(
acceptedFiles
);
console
.
log
(
repeatAndUploaderFileList
);
if
(
repeatAndUploaderFileList
.
repeatFileList
.
length
>
0
)
{
message
.
error
(
`“
${
repeatAndUploaderFileList
.
repeatFileList
.
map
((
i
:
any
)
=>
i
.
name
)
.
join
(
"、"
)}
”文件已存在`
);
}
}
// 插入新的文件列表
// 插入新的文件列表
const
popLength
=
10
-
fileList
.
length
;
const
popLength
=
10
-
fileList
.
length
;
let
newFileList
=
[...
acceptedFiles
.
slice
(
0
,
popLength
),
...
fileList
];
let
newFileList
=
[
...
repeatAndUploaderFileList
.
uploderFileList
.
slice
(
0
,
popLength
),
...
fileList
,
];
setFileList
(
newFileList
);
setFileList
(
newFileList
);
},
},
[
fileList
,
list
,
message
]
[
fileList
,
message
,
nowNameList
]
);
);
const
getRepeatName
=
(
fList
:
Array
<
any
>
,
Alist
:
Array
<
any
>
)
=>
{
//
const getRepeatName = (fList: Array<any>, Alist: Array<any>) => {
let
repeatName
=
""
;
//
let repeatName = "";
Alist
.
forEach
((
aItem
)
=>
{
//
Alist.forEach((aItem) => {
fList
.
forEach
((
fItem
:
any
)
=>
{
//
fList.forEach((fItem: any) => {
if
(
fItem
.
name
===
aItem
.
name
)
{
//
if (fItem.name === aItem.name) {
repeatName
=
fItem
.
name
;
//
repeatName = fItem.name;
}
//
}
});
//
});
});
//
});
return
repeatName
;
//
return repeatName;
};
//
};
const
{
getRootProps
,
getInputProps
,
isDragActive
}
=
useDropzone
({
onDrop
});
const
{
getRootProps
,
getInputProps
,
isDragActive
}
=
useDropzone
({
onDrop
});
...
@@ -64,11 +103,11 @@ const UpLoaderFile = observer((props: any) => {
...
@@ -64,11 +103,11 @@ const UpLoaderFile = observer((props: any) => {
return
{
return
{
id
:
uuid
(),
id
:
uuid
(),
open
:
false
,
open
:
false
,
list
:
item
,
list
:
[],
file
:
item
,
isPermanence
:
true
,
isPermanence
:
true
,
};
};
})
||
[];
})
||
[];
console
.
log
(
newFileList
);
toJS
(
fileListStore
?.
setNewFileList
)(
newFileList
);
toJS
(
fileListStore
?.
setNewFileList
)(
newFileList
);
};
};
...
@@ -98,9 +137,7 @@ const UpLoaderFile = observer((props: any) => {
...
@@ -98,9 +137,7 @@ const UpLoaderFile = observer((props: any) => {
};
};
// 1,048,576
// 1,048,576
const
renderSize
=
(
item
:
any
)
=>
{
const
renderSize
=
(
item
:
any
)
=>
{
return
(
return
<
span
>
{
item
.
size
?
storageUnitFromB
(
Number
(
item
.
size
))
:
"-"
}
</
span
>;
<
span
>
{
item
.
size
?
`${getMbfromB(Number(item.size))}MB`
:
"-"
}
</
span
>
);
};
};
const
handleRowDelete
=
(
index
:
number
)
=>
{
const
handleRowDelete
=
(
index
:
number
)
=>
{
...
@@ -183,12 +220,14 @@ const UpLoaderFile = observer((props: any) => {
...
@@ -183,12 +220,14 @@ const UpLoaderFile = observer((props: any) => {
fontSize
:
"12px"
,
fontSize
:
"12px"
,
lineHeight
:
"20px"
,
lineHeight
:
"20px"
,
color
:
"#8A9099"
,
color
:
"#8A9099"
,
// padding: "12px 24px",
}
}
}
}
tableBoySx=
{
{
tableBoySx=
{
{
backgroundColor
:
backgroundColor
:
fileList
.
length
>=
10
?
"rgba(255, 0, 0, 0.6)"
:
""
,
fileList
.
length
>=
10
?
"rgba(255, 0, 0, 0.6)"
:
""
,
}
}
}
}
tableContainerStyle=
{
{
maxHeight
:
"300px"
,
}
}
></
Table
>
></
Table
>
</
div
>
</
div
>
{
fileList
.
length
===
0
&&
(
{
fileList
.
length
===
0
&&
(
...
...
src/views/Project/ProjectData/index.tsx
View file @
1694936d
...
@@ -28,7 +28,9 @@ import DialogActions from "@mui/material/DialogActions";
...
@@ -28,7 +28,9 @@ import DialogActions from "@mui/material/DialogActions";
import
DialogContent
from
"@mui/material/DialogContent"
;
import
DialogContent
from
"@mui/material/DialogContent"
;
import
DialogContentText
from
"@mui/material/DialogContentText"
;
import
DialogContentText
from
"@mui/material/DialogContentText"
;
import
DialogTitle
from
"@mui/material/DialogTitle"
;
import
DialogTitle
from
"@mui/material/DialogTitle"
;
import
NoProject
from
"@/components/NoProject"
;
import
usePass
from
"@/hooks/usePass"
;
import
usePass
from
"@/hooks/usePass"
;
import
{
storageUnitFromB
}
from
"@/utils/util"
;
import
{
import
{
getDataFind
,
getDataFind
,
getDataFileSearch
,
getDataFileSearch
,
...
@@ -63,9 +65,16 @@ const ProjectData = observer(() => {
...
@@ -63,9 +65,16 @@ const ProjectData = observer(() => {
const
isPass
=
usePass
();
const
isPass
=
usePass
();
const
Message
=
useMessage
();
const
Message
=
useMessage
();
const
{
currentProjectStore
}
=
useStores
();
const
{
currentProjectStore
}
=
useStores
();
const
projectId
=
useMemo
(()
=>
{
// const [fileToken, setFileToken] = useState("");
return
toJS
(
currentProjectStore
.
currentProjectInfo
.
id
);
const
fileToken
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
filetoken
);
},
[
currentProjectStore
]);
const
projectId
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
id
);
// const projectId = useMemo(() => {
// console.log(
// toJS(currentProjectStore.currentProjectInfo.id),
// "toJS(currentProjectStore.currentProjectInfo.id)"
// );
// return toJS(currentProjectStore.currentProjectInfo.id);
// }, [currentProjectStore]);
// 当前文件路径
// 当前文件路径
const
[
path
,
setPath
]
=
useState
(
"/"
);
const
[
path
,
setPath
]
=
useState
(
"/"
);
const
[
tableLoadding
,
setTableLoadding
]
=
useState
(
false
);
const
[
tableLoadding
,
setTableLoadding
]
=
useState
(
false
);
...
@@ -80,7 +89,6 @@ const ProjectData = observer(() => {
...
@@ -80,7 +89,6 @@ const ProjectData = observer(() => {
// 复选框选中的文件名称数组
// 复选框选中的文件名称数组
const
[
selectIds
,
setSelectIds
]
=
useState
<
Array
<
string
>>
([]);
const
[
selectIds
,
setSelectIds
]
=
useState
<
Array
<
string
>>
([]);
const
[
keyWord
,
setKeyWord
]
=
useState
(
""
);
const
[
keyWord
,
setKeyWord
]
=
useState
(
""
);
const
[
fileToken
,
setFileToken
]
=
useState
(
""
);
// 文件夹、文件列表
// 文件夹、文件列表
const
[
list
,
setList
]
=
useState
<
any
>
([]);
const
[
list
,
setList
]
=
useState
<
any
>
([]);
// 数据集列表 不带文件
// 数据集列表 不带文件
...
@@ -108,12 +116,17 @@ const ProjectData = observer(() => {
...
@@ -108,12 +116,17 @@ const ProjectData = observer(() => {
}
}
},
[
list
,
dataSetList
,
activeTab
]);
},
[
list
,
dataSetList
,
activeTab
]);
// 全(文件、文件夹、数据集)列表
const
allList
=
useMemo
(()
=>
{
return
[...
list
,
...
dataSetList
];
},
[
list
,
dataSetList
]);
// 获取文件token
// 获取文件token
const
{
run
:
getDataFileTokenRun
}
=
useMyRequest
(
getDataFileToken
,
{
//
const { run: getDataFileTokenRun } = useMyRequest(getDataFileToken, {
onSuccess
:
(
res
:
any
)
=>
{
//
onSuccess: (res: any) => {
setFileToken
(
res
.
data
);
//
setFileToken(res.data);
},
//
},
});
//
});
// 全局搜索数据集
// 全局搜索数据集
const
{
run
:
getDataFileSearchRun
}
=
useMyRequest
(
getDataFileSearch
,
{
const
{
run
:
getDataFileSearchRun
}
=
useMyRequest
(
getDataFileSearch
,
{
...
@@ -149,7 +162,7 @@ const ProjectData = observer(() => {
...
@@ -149,7 +162,7 @@ const ProjectData = observer(() => {
// 获取某路径下的数据集
// 获取某路径下的数据集
const
getDataSetList
=
useCallback
(()
=>
{
const
getDataSetList
=
useCallback
(()
=>
{
if
(
keyWord
)
{
if
(
keyWord
&&
projectId
)
{
return
;
return
;
}
else
{
}
else
{
return
getDataFindRun
({
return
getDataFindRun
({
...
@@ -161,7 +174,7 @@ const ProjectData = observer(() => {
...
@@ -161,7 +174,7 @@ const ProjectData = observer(() => {
// 全局搜索数据集
// 全局搜索数据集
const
getDataSetListSearch
=
useCallback
(()
=>
{
const
getDataSetListSearch
=
useCallback
(()
=>
{
if
(
keyWord
)
{
if
(
keyWord
&&
projectId
)
{
return
getDataFileSearchRun
({
return
getDataFileSearchRun
({
projectId
:
projectId
as
string
,
projectId
:
projectId
as
string
,
name
:
keyWord
,
name
:
keyWord
,
...
@@ -246,11 +259,11 @@ const ProjectData = observer(() => {
...
@@ -246,11 +259,11 @@ const ProjectData = observer(() => {
};
};
// 项目切换时重新获取文件token
// 项目切换时重新获取文件token
useEffect
(()
=>
{
//
useEffect(() => {
getDataFileTokenRun
({
//
getDataFileTokenRun({
id
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
//
id: currentProjectStore.currentProjectInfo.id as string,
});
//
});
},
[
getDataFileTokenRun
,
currentProjectStore
]);
//
}, [getDataFileTokenRun, currentProjectStore]);
// 搜索值改变
// 搜索值改变
const
handleKeyWordChange
=
(
e
:
any
)
=>
{
const
handleKeyWordChange
=
(
e
:
any
)
=>
{
...
@@ -350,9 +363,7 @@ const ProjectData = observer(() => {
...
@@ -350,9 +363,7 @@ const ProjectData = observer(() => {
if
(
item
.
type
===
"dataSet"
)
{
if
(
item
.
type
===
"dataSet"
)
{
return
`
${
item
.
size
}
条`
;
return
`
${
item
.
size
}
条`
;
}
}
return
`
${
return
`
${
item
.
size
?
storageUnitFromB
(
Number
(
item
.
size
))
:
"-"
}
`
;
item
.
size
?
String
((
Number
(
item
.
size
)
/
1048576
).
toFixed
(
2
))
+
"MB"
:
"-"
}
`
;
};
};
// table配置
// table配置
...
@@ -380,7 +391,7 @@ const ProjectData = observer(() => {
...
@@ -380,7 +391,7 @@ const ProjectData = observer(() => {
size=
"small"
size=
"small"
onClick=
{
()
=>
hanleShowMoveFileDialog
(
item
)
}
onClick=
{
()
=>
hanleShowMoveFileDialog
(
item
)
}
disabled=
{
disabled=
{
selectIds
.
length
>
0
&&
!
isPass
(
"PROJECT_DATA_MOVE"
,
"USER"
)
selectIds
.
length
>
0
||
!
isPass
(
"PROJECT_DATA_MOVE"
,
"USER"
)
}
}
>
>
移动至
移动至
...
@@ -392,7 +403,7 @@ const ProjectData = observer(() => {
...
@@ -392,7 +403,7 @@ const ProjectData = observer(() => {
color=
"error"
color=
"error"
onClick=
{
()
=>
hanleDeleteFile
(
item
)
}
onClick=
{
()
=>
hanleDeleteFile
(
item
)
}
disabled=
{
disabled=
{
selectIds
.
length
>
0
&&
!
isPass
(
"PROJECT_DATA_DELETE"
,
"USER"
)
selectIds
.
length
>
0
||
!
isPass
(
"PROJECT_DATA_DELETE"
,
"USER"
)
}
}
>
>
删除
删除
...
@@ -423,7 +434,11 @@ const ProjectData = observer(() => {
...
@@ -423,7 +434,11 @@ const ProjectData = observer(() => {
};
};
// 删除文件
// 删除文件
const
handleDeleteDialogClose
=
()
=>
{
const
handleDeleteDialogClose
=
(
event
:
any
=
{},
reason
:
any
=
"other"
)
=>
{
// 点击弹窗外不关闭弹窗
if
(
reason
===
"backdropClick"
)
{
return
;
}
setDeleteDialogOpen
(
false
);
setDeleteDialogOpen
(
false
);
};
};
...
@@ -468,7 +483,7 @@ const ProjectData = observer(() => {
...
@@ -468,7 +483,7 @@ const ProjectData = observer(() => {
:
`
${
path
}
/
${
currentOperateFile
.
name
}
`
;
:
`
${
path
}
/
${
currentOperateFile
.
name
}
`
;
CloudEController
.
JobOutFileDel
(
CloudEController
.
JobOutFileDel
(
deletePath
,
deletePath
,
fileToken
,
fileToken
as
string
,
projectId
as
string
projectId
as
string
)?.
then
((
res
)
=>
{
)?.
then
((
res
)
=>
{
Message
.
success
(
"删除成功"
);
Message
.
success
(
"删除成功"
);
...
@@ -499,7 +514,7 @@ const ProjectData = observer(() => {
...
@@ -499,7 +514,7 @@ const ProjectData = observer(() => {
.
join
(
" "
);
.
join
(
" "
);
CloudEController
.
JobOutFileDel
(
CloudEController
.
JobOutFileDel
(
deletePath
,
deletePath
,
fileToken
,
fileToken
as
string
,
projectId
as
string
projectId
as
string
)?.
then
((
res
)
=>
{
)?.
then
((
res
)
=>
{
Message
.
success
(
"删除成功"
);
Message
.
success
(
"删除成功"
);
...
@@ -512,7 +527,7 @@ const ProjectData = observer(() => {
...
@@ -512,7 +527,7 @@ const ProjectData = observer(() => {
}
else
{
}
else
{
CloudEController
.
JobOutFileDel
(
CloudEController
.
JobOutFileDel
(
deletePath
,
deletePath
,
fileToken
,
fileToken
as
string
,
projectId
as
string
projectId
as
string
)?.
then
((
res
)
=>
{
)?.
then
((
res
)
=>
{
Message
.
success
(
"删除成功"
);
Message
.
success
(
"删除成功"
);
...
@@ -601,6 +616,7 @@ const ProjectData = observer(() => {
...
@@ -601,6 +616,7 @@ const ProjectData = observer(() => {
}
}
},
[
path
]);
},
[
path
]);
if
(
currentProjectStore
.
currentProjectInfo
.
name
)
{
return
(
return
(
<
ThemeProvider
theme=
{
theme
}
>
<
ThemeProvider
theme=
{
theme
}
>
<
div
className=
{
style
.
projectData
}
>
<
div
className=
{
style
.
projectData
}
>
...
@@ -788,11 +804,11 @@ const ProjectData = observer(() => {
...
@@ -788,11 +804,11 @@ const ProjectData = observer(() => {
<
UpLoaderFile
<
UpLoaderFile
onRef=
{
UpLoaderFileRef
}
onRef=
{
UpLoaderFileRef
}
path=
{
path
}
path=
{
path
}
list=
{
l
ist
}
list=
{
allL
ist
}
></
UpLoaderFile
>
></
UpLoaderFile
>
<
AddFolder
<
AddFolder
onRef=
{
addFolderRef
}
onRef=
{
addFolderRef
}
list=
{
l
ist
}
list=
{
allL
ist
}
path=
{
path
}
path=
{
path
}
refresh=
{
handleRefresh
}
refresh=
{
handleRefresh
}
fileToken=
{
fileToken
}
fileToken=
{
fileToken
}
...
@@ -812,6 +828,9 @@ const ProjectData = observer(() => {
...
@@ -812,6 +828,9 @@ const ProjectData = observer(() => {
</
div
>
</
div
>
</
ThemeProvider
>
</
ThemeProvider
>
);
);
}
else
{
return
<
NoProject
/>;
}
});
});
export
default
ProjectData
;
export
default
ProjectData
;
src/views/Project/ProjectSetting/BaseInfo/index.tsx
View file @
1694936d
...
@@ -28,7 +28,10 @@ import Loading from "@/views/Loading";
...
@@ -28,7 +28,10 @@ import Loading from "@/views/Loading";
import
MyDialog
from
"@/components/mui/MyDialog"
;
import
MyDialog
from
"@/components/mui/MyDialog"
;
import
{
getProjectList
}
from
"../../project"
;
import
{
getProjectList
}
from
"../../project"
;
import
{
checkIsNumberLetterChinese
}
from
"@/utils/util"
;
import
{
checkIsNumberLetterChinese
}
from
"@/utils/util"
;
import
{
setFileServerEndPointLocalStorage
}
from
"@/views/Project/project"
;
import
{
setFileServerEndPointLocalStorage
,
getFiletokenAccordingToId
,
}
from
"@/views/Project/project"
;
type
zoneIdOption
=
{
type
zoneIdOption
=
{
id
:
string
;
id
:
string
;
...
@@ -190,8 +193,15 @@ const BaseInfo = observer(() => {
...
@@ -190,8 +193,15 @@ const BaseInfo = observer(() => {
localStorage
.
setItem
(
"fileServerEndPoint"
,
""
);
localStorage
.
setItem
(
"fileServerEndPoint"
,
""
);
setProjectInfo
({});
setProjectInfo
({});
}
else
{
}
else
{
projectList
[
0
].
filetoken
=
getFiletokenAccordingToId
(
projectList
[
0
].
id
);
currentProjectStore
.
changeProject
(
projectList
[
0
]);
currentProjectStore
.
changeProject
(
projectList
[
0
]);
setFileServerEndPointLocalStorage
(
projectList
[
0
].
zoneId
);
setFileServerEndPointLocalStorage
(
projectList
[
0
].
zoneId
);
getFiletokenAccordingToId
(
projectList
[
0
].
id
).
then
((
res
)
=>
{
projectList
[
0
].
filetoken
=
res
;
currentProjectStore
.
changeProject
(
projectList
[
0
]);
});
setProjectInfo
(
projectList
[
0
]);
setProjectInfo
(
projectList
[
0
]);
}
}
},
},
...
...
src/views/Project/ProjectSetting/ProjectMembers/components/AddMember.tsx
View file @
1694936d
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-1
1 15:24:15
* @LastEditTime: 2022-06-1
5 19:04:11
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
...
@@ -35,16 +35,9 @@ const AddMember = observer((props: IProps) => {
...
@@ -35,16 +35,9 @@ const AddMember = observer((props: IProps) => {
const
[
projectMember
,
setProjectMember
]
=
useState
(
""
);
const
[
projectMember
,
setProjectMember
]
=
useState
(
""
);
const
[
filterTableData
,
setFilterTableData
]
=
useState
([]);
const
[
filterTableData
,
setFilterTableData
]
=
useState
([]);
const
[
checkData
,
setCheckData
]
=
useState
<
string
[]
>
([]);
const
[
checkData
,
setCheckData
]
=
useState
<
string
[]
>
([]);
const
[
selectOptions
,
setSelectOptions
]
=
useState
<
IOption
[]
>
([]);
const
Message
=
useMessage
();
const
Message
=
useMessage
();
const
selectOptions
=
useMemo
(()
=>
{
return
[
{
value
:
"VIEWER"
,
label
:
"查看者"
},
{
value
:
"DEVELOPER"
,
label
:
"研发者"
},
{
value
:
"MANAGER"
,
label
:
"管理者"
},
];
},
[]);
const
changePermission
=
useCallback
(
const
changePermission
=
useCallback
(
(
val
:
IOption
,
index
:
number
)
=>
{
(
val
:
IOption
,
index
:
number
)
=>
{
const
tableDataIndex
=
tableData
[
index
]
as
any
;
const
tableDataIndex
=
tableData
[
index
]
as
any
;
...
@@ -56,7 +49,8 @@ const AddMember = observer((props: IProps) => {
...
@@ -56,7 +49,8 @@ const AddMember = observer((props: IProps) => {
[
tableData
]
[
tableData
]
);
);
const
columns
=
[
const
columns
=
useMemo
(()
=>
{
return
[
{
id
:
"checkbox"
,
width
:
50
},
{
id
:
"checkbox"
,
width
:
50
},
{
id
:
"username"
,
label
:
"项目成员"
,
width
:
160
},
{
id
:
"username"
,
label
:
"项目成员"
,
width
:
160
},
{
{
...
@@ -67,6 +61,7 @@ const AddMember = observer((props: IProps) => {
...
@@ -67,6 +61,7 @@ const AddMember = observer((props: IProps) => {
const
defaultValue
=
selectOptions
.
filter
(
const
defaultValue
=
selectOptions
.
filter
(
(
every
)
=>
every
.
value
===
item
(
every
)
=>
every
.
value
===
item
);
);
console
.
log
(
selectOptions
,
defaultValue
,
"111"
);
return
(
return
(
<
MySelect
<
MySelect
input=
{
<
OutlinedInput
/>
}
input=
{
<
OutlinedInput
/>
}
...
@@ -83,7 +78,25 @@ const AddMember = observer((props: IProps) => {
...
@@ -83,7 +78,25 @@ const AddMember = observer((props: IProps) => {
},
},
},
},
];
];
},
[
changePermission
,
selectOptions
]);
useEffect
(()
=>
{
if
(
addMemberDialog
)
{
http
.
get
<
IResponse
<
any
>
>
("/cpp/project/listroles").then((res) =
>
{
const
arr
=
[];
const
{
data
}
=
res
;
for
(
const
key
in
data
)
{
arr
.
push
({
label
:
String
(
data
[
key
]),
value
:
key
,
});
}
setSelectOptions
(
arr
);
}
);
}
}, [addMemberDialog, http]);
/** 过滤表格数据 */
useEffect(() =
>
{
useEffect(() =
>
{
if
(
!!
projectMember
)
{
if
(
!!
projectMember
)
{
const
newVal
=
const
newVal
=
...
@@ -96,6 +109,7 @@ const AddMember = observer((props: IProps) => {
...
@@ -96,6 +109,7 @@ const AddMember = observer((props: IProps) => {
}
}
}
, [projectMember, tableData]);
}
, [projectMember, tableData]);
/** 获取表格数据 */
useEffect(() =
>
{
useEffect(() =
>
{
if
(
!
addMemberDialog
)
return
;
if
(
!
addMemberDialog
)
return
;
const
projectInfo
=
toJS
(
currentProjectStore
?.
currentProjectInfo
);
const
projectInfo
=
toJS
(
currentProjectStore
?.
currentProjectInfo
);
...
@@ -104,9 +118,7 @@ const AddMember = observer((props: IProps) => {
...
@@ -104,9 +118,7 @@ const AddMember = observer((props: IProps) => {
params
:
{
id
:
projectInfo
?.
id
||
""
},
params
:
{
id
:
projectInfo
?.
id
||
""
},
}
)
}
)
.then((res) =
>
{
.then((res) =
>
{
if
(
res
.
data
.
length
)
{
setTableData
(
res
?.
data
);
setTableData
(
res
?.
data
);
}
}
);
}
);
}
, [currentProjectStore?.currentProjectInfo, http, addMemberDialog]);
}
, [currentProjectStore?.currentProjectInfo, http, addMemberDialog]);
...
...
src/views/Project/ProjectSetting/ProjectMembers/components/RemoveItem.tsx
View file @
1694936d
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-
07 15:55:26
* @LastEditTime: 2022-06-
15 13:50:54
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
...
@@ -34,10 +34,6 @@ const RemoveItem = observer((props: IProps) => {
...
@@ -34,10 +34,6 @@ const RemoveItem = observer((props: IProps) => {
};
};
const
onConfirm
=
()
=>
{
const
onConfirm
=
()
=>
{
const
projectInfo
=
toJS
(
currentProjectStore
?.
currentProjectInfo
);
const
projectInfo
=
toJS
(
currentProjectStore
?.
currentProjectInfo
);
console
.
log
(
111111
,
{
id
:
projectInfo
?.
id
||
""
,
username
:
removeDialog
.
username
,
});
http
http
.
del
<
IResponse
<
any
>>
(
.
del
<
IResponse
<
any
>>
(
`/cpp/project/removemember?id=
${
projectInfo
?.
id
||
""
}
&
username
=
$
{
`/cpp/project/removemember?id=
${
projectInfo
?.
id
||
""
}
&
username
=
$
{
...
...
src/views/Project/ProjectSetting/ProjectMembers/index.tsx
View file @
1694936d
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-1
0 18:08:00
* @LastEditTime: 2022-06-1
5 18:53:01
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
...
@@ -154,7 +154,7 @@ const ProjectMembers = () => {
...
@@ -154,7 +154,7 @@ const ProjectMembers = () => {
sx=
{
{
width
:
340
,
height
:
32
}
}
sx=
{
{
width
:
340
,
height
:
32
}
}
endAdornment=
{
<
SearchIcon
style=
{
{
color
:
"#8A9099"
}
}
/>
}
endAdornment=
{
<
SearchIcon
style=
{
{
color
:
"#8A9099"
}
}
/>
}
/>
/>
{
isProjectOwner
(
projectOwner
)
?
(
{
currentProjectStore
?.
currentProjectInfo
?.
projectRole
===
"OWNER"
?
(
<
Button
<
Button
style=
{
{
backgroundColor
:
"#1370FF "
}
}
style=
{
{
backgroundColor
:
"#1370FF "
}
}
variant=
"contained"
variant=
"contained"
...
...
src/views/Project/components/AddProject/index.tsx
View file @
1694936d
...
@@ -8,6 +8,10 @@ import { useMessage } from "@/components/MySnackbar";
...
@@ -8,6 +8,10 @@ import { useMessage } from "@/components/MySnackbar";
import
{
getProjectList
}
from
"../../project"
;
import
{
getProjectList
}
from
"../../project"
;
import
{
useStores
}
from
"@/store"
;
import
{
useStores
}
from
"@/store"
;
import
{
checkIsNumberLetterChinese
}
from
"@/utils/util"
;
import
{
checkIsNumberLetterChinese
}
from
"@/utils/util"
;
import
{
setFileServerEndPointLocalStorage
,
getFiletokenAccordingToId
,
}
from
"@/views/Project/project"
;
type
zoneIdOption
=
{
type
zoneIdOption
=
{
id
:
string
;
id
:
string
;
...
@@ -45,6 +49,18 @@ const AddProject = (props: any) => {
...
@@ -45,6 +49,18 @@ const AddProject = (props: any) => {
message
.
success
(
"新建项目成功"
);
message
.
success
(
"新建项目成功"
);
const
projectList
=
await
getProjectList
();
const
projectList
=
await
getProjectList
();
currentProjectStore
.
setProjectList
(
projectList
);
currentProjectStore
.
setProjectList
(
projectList
);
let
project
:
any
=
{};
projectList
.
forEach
((
item
:
any
)
=>
{
if
(
item
.
name
===
name
)
{
project
=
{
...
item
};
}
});
currentProjectStore
.
changeProject
(
project
);
setFileServerEndPointLocalStorage
(
project
.
zoneId
);
getFiletokenAccordingToId
(
project
.
id
).
then
((
res
)
=>
{
project
.
filetoken
=
res
;
currentProjectStore
.
changeProject
(
project
);
});
}
}
},
},
onError
:
()
=>
{
onError
:
()
=>
{
...
...
src/views/Project/components/CurrentProject/index.tsx
View file @
1694936d
...
@@ -7,7 +7,10 @@ import ProjectListPopper from "../ProjectListPopper";
...
@@ -7,7 +7,10 @@ import ProjectListPopper from "../ProjectListPopper";
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
{
observer
}
from
"mobx-react-lite"
;
import
{
observer
}
from
"mobx-react-lite"
;
import
AddProject
from
"../AddProject"
;
import
AddProject
from
"../AddProject"
;
import
{
setFileServerEndPointLocalStorage
}
from
"@/views/Project/project"
;
import
{
setFileServerEndPointLocalStorage
,
getFiletokenAccordingToId
,
}
from
"@/views/Project/project"
;
const
CurrentProject
=
observer
(()
=>
{
const
CurrentProject
=
observer
(()
=>
{
const
{
currentProjectStore
}
=
useStores
();
const
{
currentProjectStore
}
=
useStores
();
...
@@ -33,6 +36,10 @@ const CurrentProject = observer(() => {
...
@@ -33,6 +36,10 @@ const CurrentProject = observer(() => {
const
handleChangeCurrentProject
=
(
project
:
any
)
=>
{
const
handleChangeCurrentProject
=
(
project
:
any
)
=>
{
currentProjectStore
.
changeProject
(
project
);
currentProjectStore
.
changeProject
(
project
);
setFileServerEndPointLocalStorage
(
project
.
zoneId
);
setFileServerEndPointLocalStorage
(
project
.
zoneId
);
getFiletokenAccordingToId
(
project
.
id
).
then
((
res
)
=>
{
project
.
filetoken
=
res
;
currentProjectStore
.
changeProject
(
project
);
});
setProjectListOpen
(
!
projectListOpen
);
setProjectListOpen
(
!
projectListOpen
);
};
};
...
...
src/views/Project/project.ts
View file @
1694936d
import
{
product
,
hpczone
}
from
"@/api/project_api"
;
import
{
product
,
hpczone
,
getDataFileToken
}
from
"@/api/project_api"
;
export
const
getProjectList
=
async
()
=>
{
export
const
getProjectList
=
async
()
=>
{
const
res
=
await
product
({
product
:
"CADD"
});
const
res
=
await
product
({
product
:
"CADD"
});
...
@@ -18,3 +18,9 @@ export const setFileServerEndPointLocalStorage = async (zoneId: string) => {
...
@@ -18,3 +18,9 @@ export const setFileServerEndPointLocalStorage = async (zoneId: string) => {
localStorage
.
setItem
(
"fileServerEndPoint"
,
fileServerEndPoint
);
localStorage
.
setItem
(
"fileServerEndPoint"
,
fileServerEndPoint
);
}
}
};
};
// 根据项目id获取文件token
export
const
getFiletokenAccordingToId
=
async
(
projectId
:
string
)
=>
{
const
res
=
await
getDataFileToken
({
id
:
projectId
});
return
res
.
data
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment