Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
biz.qingxiao.com
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
wangxuelai
biz.qingxiao.com
Commits
a096ee83
Commit
a096ee83
authored
Feb 14, 2020
by
wangtao
Browse files
Options
Browse Files
Download
Plain Diff
'最新代码提交'
parents
5a760857
a6321435
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
828 additions
and
94 deletions
+828
-94
index.html
index.html
+1
-1
createtheme.js
src/models/createtheme.js
+251
-69
webapp.js
src/models/webapp.js
+5
-5
index.js
src/pages/404/index.js
+0
-1
ThemeEditor.js
src/pages/newtheme/ThemeEditor.js
+9
-1
ThemeEditor.less
src/pages/newtheme/ThemeEditor.less
+25
-0
index.js
src/pages/newtheme/calendarclock/index.js
+12
-0
ContentSetting.js
src/pages/newtheme/customsclock/ContentSetting.js
+12
-0
Unclock.js
src/pages/newtheme/customsclock/Unclock.js
+65
-10
Unclock.less
src/pages/newtheme/customsclock/Unclock.less
+1
-1
UnclockDetail.js
src/pages/newtheme/customsclock/UnclockDetail.js
+12
-0
addStoreCount.js
src/pages/newtheme/customsclock/addStoreCount.js
+12
-0
ThemeEditor.js
src/pages/newtheme/customsclock/components/ThemeEditor.js
+162
-0
ThemeEditor.less
src/pages/newtheme/customsclock/components/ThemeEditor.less
+230
-0
index.js
src/pages/newtheme/jobclock/index.js
+12
-0
index.js
src/pages/thememgt/index.js
+3
-5
uploader.js
src/services/uploader.js
+16
-1
No files found.
index.html
View file @
a096ee83
...
...
@@ -18,5 +18,5 @@
</head>
<body>
<div
id=
"root"
></div>
<script
type=
"text/javascript"
src=
"
https://cdn.img.shangjiadao.cn/qingxiao/biz/dist/main.828990
.js"
></script></body>
<script
type=
"text/javascript"
src=
"
/dist/main.05bc89
.js"
></script></body>
</html>
\ No newline at end of file
src/models/createtheme.js
View file @
a096ee83
...
...
@@ -116,7 +116,47 @@ export default {
push_time
:
'18:00'
,
sign_up_status
:
2
,
banner
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2c/sharemoretheme/newunlockbg.png'
,
content
:
[],
content
:
[
{
title
:
'训练营是如何开展学习的?'
,
content
:
[{
type
:
'text'
,
value
:
'1.全程陪伴练字教学,我们通过听课+作业+点评+群内解答等互动形式,提高学习效果'
+
'
\
n'
+
'2.国家级书法名师亲自授课,指导你快速学习正确的握笔姿势和练字方法'
+
'
\
n'
+
'3.从零基础讲起,适合小白快速入门,课程系统全面,有经验的学员也能得到进一步提高;'
+
'
\
n'
+
'4.我们的每一位同学都将得到一对一教师指导,每天督促学习,陪伴式成长'
+
'适合人群
\
n'
+
'(1)零基础练字学员
\
n'
+
'(2)有一点基础,想提升的学员
\
n'
+
'(3)节假日期间想快速练好字的学员'
,
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/title-1.png'
},
],
},
{
title
:
'加入训练营孩子能收获什么?'
,
content
:
[
{
type
:
'text'
,
value
:
'训练营共14关,不仅学习专业的练字技能,通关之后将获得机构赠送精美礼品(1)价值399元伯尔尼斯电饭锅一台'
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/ricecooker.png'
},
{
type
:
'text'
,
value
:
'(2)价值599元小天才电话手表一个'
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/shoubiao.png'
},
],
},
{
title
:
'教学老师'
,
content
:
[
{
type
:
'text'
,
value
:
'洛子帅, 书法练字训练营创始人,杭州阳关灿烂教育教学主管,专业书法教师,已帮助3000多人写好字。'
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/laoshi.png'
},
],
},
{
title
:
'毕业学生作品'
,
content
:
[{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/works.png'
}],
},
],
sign_up_content
:
''
,
},
radioname
:
''
,
...
...
@@ -126,6 +166,7 @@ export default {
storeId
:
0
,
// 闯关ID
subjectList
:
[],
storeImg
:
''
,
progressRate
:
0
,
},
subscriptions
:
{
setup
({
dispatch
,
history
})
{
// eslint-disable-line
...
...
@@ -471,7 +512,12 @@ export default {
push_time
:
emigratedDate
.
data
.
push_time
,
sign_up_status
:
emigratedDate
.
data
.
sign_up_status
,
banner
:
emigratedDate
.
data
.
banner
?
emigratedDate
.
data
.
banner
:
''
,
content
:
emigratedDate
.
data
.
introduce
?
JSON
.
parse
(
emigratedDate
.
data
.
introduce
)
:
[],
content
:
emigratedDate
.
data
.
introduce
&&
emigratedDate
.
data
.
introduce
!=
null
&&
JSON
.
parse
(
emigratedDate
.
data
.
introduce
)
&&
JSON
.
parse
(
emigratedDate
.
data
.
introduce
)[
0
]
&&
JSON
.
parse
(
emigratedDate
.
data
.
introduce
)[
0
].
content
?
JSON
.
parse
(
emigratedDate
.
data
.
introduce
)
:
[
{
title
:
emigratedDate
.
data
.
introduce
&&
emigratedDate
.
data
.
introduce
!=
null
&&
JSON
.
parse
(
emigratedDate
.
data
.
introduce
).
title
?
JSON
.
parse
(
emigratedDate
.
data
.
introduce
).
title
:
''
,
content
:
emigratedDate
.
data
.
introduce
&&
emigratedDate
.
data
.
introduce
!=
null
&&
JSON
.
parse
(
emigratedDate
.
data
.
introduce
).
content
?
JSON
.
parse
(
emigratedDate
.
data
.
introduce
).
content
:
(
JSON
.
parse
(
emigratedDate
.
data
.
introduce
)
||
[]),
},
],
},
radioname
:
emigratedDate
.
data
.
sign_up_content
?
JSON
.
parse
(
emigratedDate
.
data
.
sign_up_content
).
radioname
:
''
,
radioList
:
emigratedDate
.
data
.
sign_up_content
?
JSON
.
parse
(
emigratedDate
.
data
.
sign_up_content
).
radioList
:
[],
...
...
@@ -488,13 +534,13 @@ export default {
},
*
goTheme
({
payload
},
{
call
,
put
,
select
})
{
const
{
index
}
=
payload
;
yield
put
(
routerRedux
.
push
(
'/sjd/newtheme'
));
yield
put
({
type
:
'updateState'
,
payload
:
{
tabIndex
:
index
,
},
});
yield
put
(
routerRedux
.
push
(
'/sjd/newtheme'
));
},
*
jobMoveContent
({
payload
},
{
call
,
put
,
select
})
{
const
{
index
,
direction
}
=
payload
;
...
...
@@ -817,7 +863,7 @@ export default {
},
*
queryimagesignature
({
payload
},
{
call
,
put
,
select
})
{
const
{
userInfo
,
sid
}
=
yield
select
(
state
=>
state
.
webapp
);
const
{
files
,
uploadtype
}
=
payload
;
const
{
files
,
uploadtype
,
contentSort
}
=
payload
;
const
file
=
files
.
files
?
files
.
files
[
0
]
:
null
;
const
REGEXP_VIDEO
=
/^image
\/\w
+/
;
const
params
=
{
type
:
1
,
token
:
userInfo
.
token
,
schoolId
:
sid
};
...
...
@@ -834,6 +880,7 @@ export default {
files
,
uploaderLoading
,
uploadtype
,
contentSort
,
},
});
}
else
{
...
...
@@ -850,6 +897,7 @@ export default {
*
uploadimage
({
payload
},
{
call
,
put
,
select
})
{
const
{
signature
,
files
,
uploaderLoading
,
uploadtype
,
contentSort
,
}
=
payload
;
const
file
=
files
.
files
?
files
.
files
[
0
]
:
null
;
const
{
...
...
@@ -900,7 +948,7 @@ export default {
},
});
}
else
if
(
uploadtype
==
'quickCustomsImg'
)
{
customsParams
.
content
.
push
({
customsParams
.
content
[
contentSort
].
content
.
push
({
type
:
'img'
,
value
:
imageUrl
,
});
...
...
@@ -924,7 +972,9 @@ export default {
*
queryvoicesignature
({
payload
},
{
call
,
put
,
select
})
{
const
{
avatorUploader
}
=
yield
select
(
state
=>
state
.
uploader
);
const
{
userInfo
,
sid
}
=
yield
select
(
state
=>
state
.
webapp
);
const
{
files
,
uploadtype
,
orgIndex
}
=
payload
;
const
{
files
,
uploadtype
,
orgIndex
,
contentSort
,
}
=
payload
;
const
file
=
files
.
files
?
files
.
files
[
0
]
:
null
;
const
REGEXP_VIDEO
=
/^audio
\/\w
+/
;
const
params
=
{
type
:
2
,
token
:
userInfo
.
token
,
schoolId
:
sid
};
...
...
@@ -940,6 +990,7 @@ export default {
files
,
uploadtype
,
orgIndex
,
contentSort
,
},
});
}
...
...
@@ -947,6 +998,7 @@ export default {
*
uploadvoice
({
payload
},
{
call
,
put
,
select
})
{
const
{
signature
,
files
,
uploadtype
,
orgIndex
,
contentSort
,
}
=
payload
;
const
file
=
files
.
files
?
files
.
files
[
0
]
:
null
;
const
uploaderLoading
=
message
.
loading
(
'正在上传录音'
,
0
);
...
...
@@ -1003,7 +1055,7 @@ export default {
},
});
}
else
if
(
uploadtype
==
'uploadVoiceCustoms'
)
{
customsParams
.
content
.
push
({
customsParams
.
content
[
contentSort
].
content
.
push
({
type
:
'voice'
,
value
:
videoUrl
,
});
...
...
@@ -1019,32 +1071,57 @@ export default {
*
queryvideosignature
({
payload
},
{
call
,
put
,
select
})
{
const
{
avatorUploader
}
=
yield
select
(
state
=>
state
.
uploader
);
const
{
userInfo
,
sid
}
=
yield
select
(
state
=>
state
.
webapp
);
const
{
files
,
uploadtype
,
orgIndex
}
=
payload
;
const
{
files
,
uploadtype
,
orgIndex
,
contentSort
,
progressCallBack
,
}
=
payload
;
const
file
=
files
.
files
?
files
.
files
[
0
]
:
null
;
if
(
file
&&
file
.
size
>
1000
*
1024
*
1024
)
{
message
.
error
(
'视频的大小不能超过1GB,请重新上传'
,
1
);
return
;
}
const
REGEXP_VIDEO
=
/^video
\/\w
+/
;
const
params
=
{
type
:
1
,
token
:
userInfo
.
token
,
schoolId
:
sid
};
let
signature
=
{};
if
(
file
&&
(
REGEXP_VIDEO
.
test
(
file
.
type
)
||
file
.
type
===
''
))
{
const
uploadSignature
=
yield
call
(
uploader
.
uploadVideoSignature
,
params
);
signature
=
uploadSignature
.
data
;
yield
put
({
type
:
'uploadvideo'
,
payload
:
{
signature
,
avatorUploader
,
files
,
uploadtype
,
orgIndex
,
},
});
if
(
uploadSignature
.
code
==
200
)
{
yield
put
({
type
:
'uploadvideo'
,
payload
:
{
signature
,
avatorUploader
,
files
,
uploadtype
,
orgIndex
,
contentSort
,
progressCallBack
,
},
});
}
else
{
yield
put
({
type
:
'updateState'
,
payload
:
{
progressRate
:
0
,
},
});
yield
put
({
type
:
'webapp/errorrequestresolve'
,
payload
:
{
data
:
uploadSignature
,
},
});
}
}
},
*
uploadvideo
({
payload
},
{
call
,
put
,
select
})
{
const
{
signature
,
files
,
uploadtype
,
orgIndex
,
contentSort
,
progressCallBack
,
}
=
payload
;
const
file
=
files
.
files
?
files
.
files
[
0
]
:
null
;
const
uploaderLoading
=
message
.
loading
(
'正在上传视频'
,
0
);
const
{
jobParams
,
calendarParams
,
emigrateParams
,
customsParams
,
}
=
yield
select
(
state
=>
state
.
createtheme
);
...
...
@@ -1056,55 +1133,73 @@ export default {
signature
:
signature
.
signature
,
file
,
url
:
signature
.
host
,
callback
:
signature
.
callback
,
};
const
uploadImg
=
yield
call
(
uploader
.
uploadVideo
,
params
);
const
uploadImg
=
yield
call
(
uploader
.
uploadVideo
,
params
,
(
res
)
=>
{
progressCallBack
(
res
);
});
const
videoUrl
=
filename
;
if
(
uploadtype
==
'uploadVideoJob'
)
{
jobParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
if
(
JSON
.
stringify
(
uploadImg
)
==
'{"status":"ok"}'
)
{
yield
put
({
type
:
'updateState'
,
payload
:
{
jobParams
:
{
...
jobParams
},
},
});
}
else
if
(
uploadtype
==
'uploadVideoCalendar'
)
{
calendarParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
yield
put
({
type
:
'updateState'
,
payload
:
{
calendarParams
:
{
...
calendarParams
},
},
});
}
else
if
(
uploadtype
==
'uploadVideoEmigrate'
)
{
emigrateParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
yield
put
({
type
:
'updateState'
,
payload
:
{
emigrateParams
:
{
...
emigrateParams
},
progressRate
:
0
,
},
});
}
else
if
(
uploadtype
==
'uploadVideoCustoms'
)
{
customsParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
if
(
uploadtype
==
'uploadVideoJob'
)
{
jobParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
yield
put
({
type
:
'updateState'
,
payload
:
{
jobParams
:
{
...
jobParams
},
},
});
}
else
if
(
uploadtype
==
'uploadVideoCalendar'
)
{
calendarParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
yield
put
({
type
:
'updateState'
,
payload
:
{
calendarParams
:
{
...
calendarParams
},
},
});
}
else
if
(
uploadtype
==
'uploadVideoEmigrate'
)
{
emigrateParams
.
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
yield
put
({
type
:
'updateState'
,
payload
:
{
emigrateParams
:
{
...
emigrateParams
},
},
});
}
else
if
(
uploadtype
==
'uploadVideoCustoms'
)
{
customsParams
.
content
[
contentSort
].
content
.
push
({
type
:
'video'
,
value
:
videoUrl
,
});
yield
put
({
type
:
'updateState'
,
payload
:
{
customsParams
:
{
...
customsParams
},
},
});
}
}
else
{
yield
put
({
type
:
'updateState'
,
payload
:
{
customsParams
:
{
...
customsParams
}
,
progressRate
:
0
,
},
});
message
.
error
(
'上传失败'
,
1
);
}
setTimeout
(
uploaderLoading
);
},
// 新闯关打卡逻辑
*
addRadio
({
payload
},
{
call
,
put
,
select
})
{
...
...
@@ -1204,9 +1299,28 @@ export default {
},
});
},
*
c
hangeCustomsText
({
payload
},
{
call
,
put
,
select
})
{
*
c
ustomsAddPlate
({
payload
},
{
call
,
put
,
select
})
{
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
customsParams
.
content
.
push
({
title
:
''
,
content
:
[
{
type
:
'text'
,
value
:
''
,
},
],
});
yield
put
({
type
:
'updateState'
,
payload
:
{
customsParams
:
{
...
customsParams
},
},
});
},
*
changeCustomsText
({
payload
},
{
call
,
put
,
select
})
{
const
{
index
}
=
payload
;
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
customsParams
.
content
[
index
].
content
.
push
({
type
:
'text'
,
value
:
''
,
});
...
...
@@ -1218,9 +1332,9 @@ export default {
});
},
*
customsChangeSize
({
payload
},
{
call
,
put
,
select
})
{
const
{
textValue
,
index
}
=
payload
;
const
{
textValue
,
index
,
sort
}
=
payload
;
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
customsParams
.
content
[
index
]
=
{
customsParams
.
content
[
sort
].
content
[
index
]
=
{
type
:
'text'
,
value
:
textValue
,
};
...
...
@@ -1231,20 +1345,31 @@ export default {
},
});
},
*
customsChangeTitle
({
payload
},
{
call
,
put
,
select
})
{
const
{
textValue
,
sort
}
=
payload
;
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
customsParams
.
content
[
sort
].
title
=
textValue
;
yield
put
({
type
:
'updateState'
,
payload
:
{
customsParams
:
{
...
customsParams
},
},
});
},
*
customsMoveContent
({
payload
},
{
call
,
put
,
select
})
{
const
{
index
,
direction
}
=
payload
;
const
{
index
,
direction
,
sort
}
=
payload
;
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
let
newContent
=
[];
newContent
=
customsParams
.
content
;
const
currentImg
=
customsParams
.
c
ontent
[
index
];
const
preImg
=
customsParams
.
c
ontent
[
index
-
1
];
const
afterImg
=
customsParams
.
c
ontent
[
index
+
1
];
newContent
=
customsParams
.
content
[
sort
].
content
;
const
currentImg
=
newC
ontent
[
index
];
const
preImg
=
newC
ontent
[
index
-
1
];
const
afterImg
=
newC
ontent
[
index
+
1
];
if
(
direction
==
'up'
)
{
newContent
.
splice
(
index
-
1
,
2
,
currentImg
,
preImg
);
}
else
if
(
direction
==
'down'
)
{
newContent
.
splice
(
index
,
2
,
afterImg
,
currentImg
);
}
customsParams
.
content
=
newContent
;
customsParams
.
content
[
sort
].
content
=
newContent
;
yield
put
({
type
:
'updateState'
,
payload
:
{
...
...
@@ -1253,9 +1378,9 @@ export default {
});
},
*
deleteCustomsImg
({
payload
},
{
call
,
put
,
select
})
{
const
{
index
}
=
payload
;
const
{
index
,
sort
}
=
payload
;
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
const
newContent
=
customsParams
.
content
;
const
newContent
=
customsParams
.
content
[
sort
].
content
;
newContent
.
splice
(
index
,
1
);
yield
put
({
type
:
'updateState'
,
...
...
@@ -1264,6 +1389,18 @@ export default {
},
});
},
*
customsDeletePlate
({
payload
},
{
call
,
put
,
select
})
{
const
{
sort
}
=
payload
;
const
{
customsParams
}
=
yield
select
(
state
=>
state
.
createtheme
);
const
newContent
=
customsParams
.
content
;
newContent
.
splice
(
sort
,
1
);
yield
put
({
type
:
'updateState'
,
payload
:
{
customsParams
:
{
...
customsParams
},
},
});
},
*
addCutomsClock
({
payload
},
{
call
,
put
,
select
})
{
const
{
sid
}
=
yield
select
(
state
=>
state
.
webapp
);
const
{
...
...
@@ -1375,7 +1512,12 @@ export default {
push_time
:
'18:00'
,
sign_up_status
:
2
,
banner
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2c/sharemoretheme/newunlockbg.png'
,
content
:
[],
content
:
[
{
title
:
''
,
content
:
[{
type
:
'text'
,
value
:
''
}],
},
],
sign_up_content
:
''
,
},
radioList
:
[],
...
...
@@ -1852,7 +1994,6 @@ export default {
},
*
goEditShowCustoms
({
payload
},
{
call
,
put
,
select
})
{
const
{
item
}
=
payload
;
console
.
log
(
item
);
yield
put
({
type
:
'updateState'
,
payload
:
{
...
...
@@ -2114,7 +2255,47 @@ export default {
push_time
:
'18:00'
,
sign_up_status
:
2
,
banner
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2c/sharemoretheme/newunlockbg.png'
,
content
:
[],
content
:
[
{
title
:
'训练营是如何开展学习的?'
,
content
:
[{
type
:
'text'
,
value
:
'1.全程陪伴练字教学,我们通过听课+作业+点评+群内解答等互动形式,提高学习效果'
+
'
\
n'
+
'2.国家级书法名师亲自授课,指导你快速学习正确的握笔姿势和练字方法'
+
'
\
n'
+
'3.从零基础讲起,适合小白快速入门,课程系统全面,有经验的学员也能得到进一步提高;'
+
'
\
n'
+
'4.我们的每一位同学都将得到一对一教师指导,每天督促学习,陪伴式成长'
+
'适合人群
\
n'
+
'(1)零基础练字学员
\
n'
+
'(2)有一点基础,想提升的学员
\
n'
+
'(3)节假日期间想快速练好字的学员'
,
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/title-1.png'
},
],
},
{
title
:
'加入训练营孩子能收获什么?'
,
content
:
[
{
type
:
'text'
,
value
:
'训练营共14关,不仅学习专业的练字技能,通关之后将获得机构赠送精美礼品(1)价值399元伯尔尼斯电饭锅一台'
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/ricecooker.png'
},
{
type
:
'text'
,
value
:
'(2)价值599元小天才电话手表一个'
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/shoubiao.png'
},
],
},
{
title
:
'教学老师'
,
content
:
[
{
type
:
'text'
,
value
:
'洛子帅, 书法练字训练营创始人,杭州阳关灿烂教育教学主管,专业书法教师,已帮助3000多人写好字。'
},
{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/laoshi.png'
},
],
},
{
title
:
'毕业学生作品'
,
content
:
[{
type
:
'img'
,
value
:
'https://cdn.img.shangjiadao.cn/qingxiao/daka/images/2b/themeeditorlock/works.png'
}],
},
],
sign_up_content
:
''
,
},
radioname
:
''
,
...
...
@@ -2124,6 +2305,7 @@ export default {
storeId
:
0
,
// 闯关ID
subjectList
:
[],
storeImg
:
''
,
progressRate
:
0
,
},
});
},
...
...
src/models/webapp.js
View file @
a096ee83
...
...
@@ -1064,11 +1064,11 @@ export default {
});
}
if
(
pathname
===
'/sjd/newtheme'
)
{
dispatch
({
type
:
'createtheme/pageInit'
,
payload
:
{
},
});
//
dispatch({
//
type: 'createtheme/pageInit',
//
payload: {
//
},
//
});
dispatch
({
type
:
'createtheme/queryClassList'
,
payload
:
{
...
...
src/pages/404/index.js
View file @
a096ee83
...
...
@@ -10,7 +10,6 @@ class Errorpage extends React.Component {
componentWillUnmount
()
{
// 卸载
}
goback
=
()
=>
{
console
.
log
(
'dsadasdsa'
);
const
{
dispatch
,
}
=
this
.
props
;
...
...
src/pages/newtheme/ThemeEditor.js
View file @
a096ee83
import
{
connect
}
from
'dva'
;
import
React
from
'react'
;
import
{
Icon
,
Divider
,
Tabs
,
Select
,
Form
,
Upload
,
Row
,
Col
,
Input
,
Radio
,
Modal
,
message
}
from
'antd'
;
import
{
Icon
,
Divider
,
Tabs
,
Select
,
Form
,
Upload
,
Row
,
Col
,
Input
,
Radio
,
Modal
,
message
,
Progress
}
from
'antd'
;
import
pageStyle
from
'./ThemeEditor.less'
;
import
{
pageIn
,
hasBtnPower
,
imagify
,
ossVideofy
,
audioorigin
}
from
'../../utils/index'
;
const
upImg
=
`
${
__IMGCDN__
}
subjectUp.png`
;
...
...
@@ -45,9 +45,16 @@ class ThemeEditor extends React.Component {
editorAddText
,
moveContent
,
editorUploadVoice
,
progressRate
,
}
=
this
.
props
;
return
(
<
div
className
=
{
pageStyle
.
container
}
>
{
progressRate
&&
progressRate
>
0
?
<
div
className
=
{
pageStyle
.
progressWrap
}
>
<
Progress
width
=
{
150
}
type
=
"circle"
percent
=
{
progressRate
}
/
>
<
p
>
{
progressRate
==
100
?
'上传成功'
:
'上传中。。。'
}
<
/p
>
<
/div> : '
'
}
<
div
className
=
{
pageStyle
.
editorwrap
}
>
{
/* eslint-disable-next-line array-callback-return,consistent-return */
}
{
commentParams
.
content
.
length
>
0
&&
commentParams
.
content
.
map
((
item
,
index
)
=>
{
...
...
@@ -124,6 +131,7 @@ class ThemeEditor extends React.Component {
<
div
className
=
{
pageStyle
.
uploadimg
}
><
input
type
=
"file"
id
=
"uploadVoice"
className
=
{
pageStyle
.
fileuploadinput
}
onChange
=
{
editorUploadVoice
}
accept
=
"audio/mp3"
/><
Icon
style
=
{{
marginRight
:
10
}}
type
=
"audio"
/>
添加录音
<
/div
>
<
div
className
=
{
pageStyle
.
uploadimg
}
><
input
type
=
"file"
id
=
"uploadVideo"
className
=
{
pageStyle
.
fileuploadinput
}
onChange
=
{
editorUploadAudio
}
accept
=
"video/mp4,video/*"
/><
Icon
style
=
{{
marginRight
:
10
}}
type
=
"video-camera"
/>
添加视频
<
/div
>
<
/div
>
<
p
className
=
{
pageStyle
.
tip
}
>
请上传视频小于
1
G
,支持
MP4
格式
<
/p
>
<
Modal
visible
=
{
previewVisible
}
footer
=
{
null
}
onCancel
=
{
this
.
handleCancel
}
>
<
img
alt
=
"图片"
style
=
{{
width
:
'100%'
}}
src
=
{
imagify
(
previewImage
)}
/
>
<
/Modal
>
...
...
src/pages/newtheme/ThemeEditor.less
View file @
a096ee83
...
...
@@ -182,3 +182,28 @@
z-index: 1;
}
}
.progressWrap {
width: 300px;
height: 300px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #f1f1f1;
border-radius: 15px;
z-index: 9999;
&>p {
font-size: 18px;
margin-top: 30px;
color: #1e8bff;
}
}
.tip {
color: #888;
margin-top: 8px;
line-height: 20px;
}
\ No newline at end of file
src/pages/newtheme/calendarclock/index.js
View file @
a096ee83
...
...
@@ -137,6 +137,14 @@ class CalendarClockForm extends React.Component {
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVideoCalendar'
,
progressCallBack
(
res
)
{
dispatch
({
type
:
'createtheme/updateState'
,
payload
:
{
progressRate
:
((
res
.
loaded
/
res
.
total
)
*
100
).
toFixed
(
0
),
},
});
},
},
});
}
...
...
@@ -262,6 +270,7 @@ class CalendarClockForm extends React.Component {
currentTimestamp
,
selectPlanDays
,
isCopy
,
progressRate
,
}
=
this
.
props
;
let
new_rest_dates
=
[];
new_rest_dates
=
[...
new
Set
(
new_rest_dates
.
concat
(...
rest_dates
))];
...
...
@@ -632,6 +641,7 @@ class CalendarClockForm extends React.Component {
deleteThemeImg
=
{
this
.
deleteCalendarImg
}
editorAddText
=
{
this
.
calendarAddText
}
moveContent
=
{
this
.
calendarMoveContent
}
progressRate
=
{
progressRate
}
/
>
<
FormItem
{...
submitFormLayout
}
style
=
{{
marginTop
:
32
}}
>
<
Button
type
=
"primary"
htmlType
=
"submit"
loading
=
{
themeAddLoading
}
>
...
...
@@ -659,6 +669,7 @@ function mapStateToProps(state) {
currentTimestamp
,
selectPlanDays
,
isCopy
,
progressRate
,
}
=
state
.
createtheme
;
return
{
themeAddLoading
,
...
...
@@ -671,6 +682,7 @@ function mapStateToProps(state) {
currentTimestamp
,
selectPlanDays
,
isCopy
,
progressRate
,
};
}
export
default
connect
(
mapStateToProps
)(
CalendarClock
);
...
...
src/pages/newtheme/customsclock/ContentSetting.js
View file @
a096ee83
...
...
@@ -103,6 +103,14 @@ class ContentSettingForm extends React.Component {
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVideoEmigrate'
,
progressCallBack
(
res
)
{
dispatch
({
type
:
'createtheme/updateState'
,
payload
:
{
progressRate
:
((
res
.
loaded
/
res
.
total
)
*
100
).
toFixed
(
0
),
},
});
},
},
});
}
...
...
@@ -233,6 +241,7 @@ class ContentSettingForm extends React.Component {
screenIsBig
,
isShowCustoms
,
subjectList
,
progressRate
,
}
=
this
.
props
;
const
formItemModalLineLayout
=
{
labelCol
:
{
...
...
@@ -330,6 +339,7 @@ class ContentSettingForm extends React.Component {
editorUploadAudio
=
{
this
.
emigrateUploadAudio
}
editorChange
=
{
this
.
changeEmigrateText
}
deleteThemeImg
=
{
this
.
deleteEmigrate
}
progressRate
=
{
progressRate
}
/
>
<
/div
>
<
/FormItem
>
...
...
@@ -488,6 +498,7 @@ function mapStateToProps(state) {
customsNumberList
,
isShowCustoms
,
subjectList
,
progressRate
,
}
=
state
.
createtheme
;
const
{
collapsed
,
screenIsBig
}
=
state
.
webapp
;
return
{
...
...
@@ -502,6 +513,7 @@ function mapStateToProps(state) {
screenIsBig
,
isShowCustoms
,
subjectList
,
progressRate
,
};
}
export
default
connect
(
mapStateToProps
)(
ContentSetting
);
...
...
src/pages/newtheme/customsclock/Unclock.js
View file @
a096ee83
...
...
@@ -15,11 +15,12 @@ import {
Collapse
,
DatePicker
,
Select
,
Radio
,
InputNumber
,
Input
,
message
,
Progress
,
}
from
'antd'
;
import
moment
from
'moment'
;
import
pageStyle
from
'./Unclock.less'
;
import
{
hasBtnPower
,
imagify
}
from
'../../../utils'
;
import
ThemeEditor
from
'..
/ThemeEditor'
;
import
{
hasBtnPower
,
imagify
}
from
'../../../utils
/index
'
;
import
ThemeEditor
One
from
'./components
/ThemeEditor'
;
const
{
TabPane
}
=
Tabs
;
const
FormItem
=
Form
.
Item
;
const
{
Option
}
=
Select
;
...
...
@@ -139,37 +140,48 @@ class UnClockForm extends React.Component {
},
});
}
customsUploadImg
=
(
e
)
=>
{
customsUploadImg
=
(
e
,
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/queryimagesignature'
,
payload
:
{
files
:
e
.
target
,
uploadtype
:
'quickCustomsImg'
,
contentSort
:
sort
,
},
});
}
customsUploadAudio
=
(
e
)
=>
{
customsUploadAudio
=
(
e
,
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/queryvideosignature'
,
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVideoCustoms'
,
contentSort
:
sort
,
progressCallBack
(
res
)
{
dispatch
({
type
:
'createtheme/updateState'
,
payload
:
{
progressRate
:
((
res
.
loaded
/
res
.
total
)
*
100
).
toFixed
(
0
),
},
});
},
},
});
}
customsUploadVoice
=
(
e
)
=>
{
customsUploadVoice
=
(
e
,
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/queryvoicesignature'
,
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVoiceCustoms'
,
contentSort
:
sort
,
},
});
}
customsChangeSize
=
(
e
,
index
)
=>
{
customsChangeSize
=
(
e
,
index
,
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
const
textValue
=
e
.
target
.
value
;
if
(
textValue
.
length
>
500
)
{
...
...
@@ -181,36 +193,72 @@ class UnClockForm extends React.Component {
payload
:
{
textValue
,
index
,
sort
,
},
});
}
customsChangeTitle
=
(
e
,
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
const
textValue
=
e
.
target
.
value
;
if
(
textValue
.
length
>
20
)
{
message
.
warning
(
'最多20字'
,
0.5
);
return
;
}
dispatch
({
type
:
'createtheme/customsChangeTitle'
,
payload
:
{
textValue
,
sort
,
},
});
}
deleteCustomsImg
=
(
index
)
=>
{
deleteCustomsImg
=
(
index
,
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/deleteCustomsImg'
,
payload
:
{
index
,
sort
,
},
});
}
customsAddText
=
()
=>
{
customsAddText
=
(
index
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/changeCustomsText'
,
payload
:
{
index
,
},
});
}
customsAddPlate
=
()
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/customsAddPlate'
,
payload
:
{
},
});
}
customsMoveContent
=
(
index
,
direction
)
=>
{
customsMoveContent
=
(
index
,
sort
,
direction
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/customsMoveContent'
,
payload
:
{
index
,
sort
,
direction
,
},
});
}
customsDeletePlate
=
(
sort
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'createtheme/customsDeletePlate'
,
payload
:
{
sort
,
},
});
}
uploadBanner
=
(
e
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
...
...
@@ -249,6 +297,7 @@ class UnClockForm extends React.Component {
radioList
,
collapsed
,
screenIsBig
,
progressRate
,
}
=
this
.
props
;
const
formItemModalLineLayout
=
{
labelCol
:
{
...
...
@@ -480,7 +529,7 @@ class UnClockForm extends React.Component {
<
/FormItem
>
<
FormItem
{...
formItemModaltypeLayout
}
label
=
"闯关介绍"
>
<
div
className
=
{
pageStyle
.
introduceWrap
}
>
<
ThemeEditor
<
ThemeEditor
One
commentParams
=
{
customsParams
}
editorUploadImg
=
{
this
.
customsUploadImg
}
editorUploadAudio
=
{
this
.
customsUploadAudio
}
...
...
@@ -489,6 +538,10 @@ class UnClockForm extends React.Component {
deleteThemeImg
=
{
this
.
deleteCustomsImg
}
moveContent
=
{
this
.
customsMoveContent
}
editorAddText
=
{
this
.
customsAddText
}
editorAddPlate
=
{
this
.
customsAddPlate
}
editorChangeTitle
=
{
this
.
customsChangeTitle
}
editorDeletePlate
=
{
this
.
customsDeletePlate
}
progressRate
=
{
progressRate
}
/
>
<
/div
>
<
/FormItem
>
...
...
@@ -533,6 +586,7 @@ function mapStateToProps(state) {
customsParams
,
radioname
,
radioList
,
progressRate
,
}
=
state
.
createtheme
;
const
{
collapsed
,
screenIsBig
}
=
state
.
webapp
;
return
{
...
...
@@ -543,6 +597,7 @@ function mapStateToProps(state) {
radioList
,
collapsed
,
screenIsBig
,
progressRate
,
};
}
export
default
connect
(
mapStateToProps
)(
UnClock
);
...
...
src/pages/newtheme/customsclock/Unclock.less
View file @
a096ee83
...
...
@@ -226,7 +226,7 @@
.introduceWrap {
width: 650px;
min-height: 319px;
padding:
0 40px 126
px;
padding:
20
px;
background-color: #fafafa;
-webkit-border-radius: 4px;
border-radius: 4px;
...
...
src/pages/newtheme/customsclock/UnclockDetail.js
View file @
a096ee83
...
...
@@ -103,6 +103,14 @@ class UnclockDetailForm extends React.Component {
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVideoEmigrate'
,
progressCallBack
(
res
)
{
dispatch
({
type
:
'createtheme/updateState'
,
payload
:
{
progressRate
:
((
res
.
loaded
/
res
.
total
)
*
100
).
toFixed
(
0
),
},
});
},
},
});
}
...
...
@@ -204,6 +212,7 @@ class UnclockDetailForm extends React.Component {
collapsed
,
screenIsBig
,
emigratedObj
,
progressRate
,
}
=
this
.
props
;
const
formItemModalLineLayout
=
{
labelCol
:
{
...
...
@@ -284,6 +293,7 @@ class UnclockDetailForm extends React.Component {
editorUploadAudio
=
{
this
.
emigrateUploadAudio
}
editorChange
=
{
this
.
changeEmigrateText
}
deleteThemeImg
=
{
this
.
deleteEmigrate
}
progressRate
=
{
progressRate
}
/
>
<
/div
>
<
/FormItem
>
...
...
@@ -434,6 +444,7 @@ function mapStateToProps(state) {
emigratedObj
,
releaseLoading
,
customsNumberList
,
progressRate
,
}
=
state
.
createtheme
;
const
{
collapsed
,
screenIsBig
}
=
state
.
webapp
;
return
{
...
...
@@ -444,6 +455,7 @@ function mapStateToProps(state) {
customsNumberList
,
collapsed
,
screenIsBig
,
progressRate
,
};
}
export
default
connect
(
mapStateToProps
)(
UnclockDetail
);
...
...
src/pages/newtheme/customsclock/addStoreCount.js
View file @
a096ee83
...
...
@@ -99,6 +99,14 @@ class UnclockDetailForm extends React.Component {
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVideoEmigrate'
,
progressCallBack
(
res
)
{
dispatch
({
type
:
'createtheme/updateState'
,
payload
:
{
progressRate
:
((
res
.
loaded
/
res
.
total
)
*
100
).
toFixed
(
0
),
},
});
},
},
});
}
...
...
@@ -192,6 +200,7 @@ class UnclockDetailForm extends React.Component {
collapsed
,
screenIsBig
,
emigratedObj
,
progressRate
,
}
=
this
.
props
;
const
formItemModalLineLayout
=
{
labelCol
:
{
...
...
@@ -256,6 +265,7 @@ class UnclockDetailForm extends React.Component {
editorUploadAudio
=
{
this
.
emigrateUploadAudio
}
editorChange
=
{
this
.
changeEmigrateText
}
deleteThemeImg
=
{
this
.
deleteEmigrate
}
progressRate
=
{
progressRate
}
/
>
<
/div
>
<
/FormItem
>
...
...
@@ -406,6 +416,7 @@ function mapStateToProps(state) {
emigratedObj
,
releaseLoading
,
customsNumberList
,
progressRate
,
}
=
state
.
createtheme
;
const
{
collapsed
,
screenIsBig
}
=
state
.
webapp
;
return
{
...
...
@@ -416,6 +427,7 @@ function mapStateToProps(state) {
customsNumberList
,
collapsed
,
screenIsBig
,
progressRate
,
};
}
export
default
connect
(
mapStateToProps
)(
UnclockDetail
);
...
...
src/pages/newtheme/customsclock/components/ThemeEditor.js
0 → 100644
View file @
a096ee83
import
{
connect
}
from
'dva'
;
import
React
from
'react'
;
import
{
Icon
,
Divider
,
Tabs
,
Select
,
Form
,
Upload
,
Row
,
Col
,
Input
,
Radio
,
Modal
,
message
,
Progress
}
from
'antd'
;
import
pageStyle
from
'./ThemeEditor.less'
;
import
{
pageIn
,
hasBtnPower
,
imagify
,
ossVideofy
,
audioorigin
}
from
'../../../../utils/index'
;
const
upImg
=
`
${
__IMGCDN__
}
subjectUp.png`
;
const
{
TabPane
}
=
Tabs
;
const
{
TextArea
}
=
Input
;
class
ThemeEditor
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
previewVisible
:
false
,
previewImage
:
''
,
};
}
componentDidMount
()
{
// 挂载
pageIn
(
'轻校-发布主题'
);
}
componentDidUpdate
()
{
}
componentWillUnmount
()
{
// 卸载
}
priviewImg
=
(
img
)
=>
{
this
.
setState
({
previewVisible
:
true
,
previewImage
:
img
,
});
}
handleCancel
=
()
=>
{
this
.
setState
({
previewVisible
:
false
,
});
}
render
()
{
const
{
previewVisible
,
previewImage
}
=
this
.
state
;
const
{
editorUploadImg
,
commentParams
,
editorUploadAudio
,
editorChange
,
deleteThemeImg
,
deleteThemeVideo
,
editorText
,
editorAddText
,
moveContent
,
editorUploadVoice
,
editorAddPlate
,
editorChangeTitle
,
editorDeletePlate
,
progressRate
,
}
=
this
.
props
;
return
(
<
div
className
=
{
pageStyle
.
container
}
>
{
progressRate
&&
progressRate
>
0
?
<
div
className
=
{
pageStyle
.
progressWrap
}
>
<
Progress
width
=
{
150
}
type
=
"circle"
percent
=
{
progressRate
}
/
>
<
p
>
{
progressRate
==
100
?
'上传成功'
:
'上传中。。。'
}
<
/p
>
<
/div> : '
'
}
<
div
className
=
{
pageStyle
.
editorwrap
}
>
{
commentParams
.
content
&&
commentParams
.
content
.
length
>
0
&&
commentParams
.
content
.
map
((
ele
,
sort
)
=>
{
return
(
<
div
className
=
{
pageStyle
.
plateWrap
}
>
<
div
className
=
{
pageStyle
.
plateDelete
}
onClick
=
{()
=>
editorDeletePlate
(
sort
)}
><
Icon
type
=
"close-circle"
theme
=
"filled"
/><
/div
>
<
Input
style
=
{{
width
:
560
}}
value
=
{
ele
.
title
}
maxLength
=
{
15
}
placeholder
=
"请输入标题,最多15个字"
onChange
=
{
e
=>
editorChangeTitle
(
e
,
sort
)}
/
>
{
ele
.
content
&&
ele
.
content
.
length
>
0
&&
ele
.
content
.
map
((
item
,
index
)
=>
{
switch
(
item
.
type
)
{
case
'text'
:
return
(
<
div
key
=
{
index
}
className
=
{
pageStyle
.
textWrap
}
>
<
TextArea
autoSize
=
{{
minRows
:
4
,
maxRows
:
10
}}
value
=
{
item
.
value
}
onChange
=
{
e
=>
editorChange
(
e
,
index
,
sort
)}
placeholder
=
"请输入打卡主题的具体要求,如:演唱歌曲《小小少年》,具体要求1.跟随伴奏唱一段副歌 2.视频录下唱歌过程 3.上传歌唱视频打卡成功 如果有该歌曲示例视频,你可以点击上传视频,供学员参考。"
style
=
{{
width
:
560
}}
maxLength
=
{
500
}
/
>
<
div
className
=
{
pageStyle
.
sizeNumber
}
>
{
item
.
value
.
length
}
/500</
div
>
<
div
className
=
{
pageStyle
.
toolList
}
>
{
index
===
0
&&
<
div
aria
-
disabled
=
"true"
className
=
{
pageStyle
.
noup
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
>
0
&&
<
div
className
=
{
pageStyle
.
up
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'up'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
===
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
nodown
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
<
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
down
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'down'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
<
div
className
=
{
pageStyle
.
delete
}
onClick
=
{()
=>
deleteThemeImg
(
index
,
sort
)}
><
Icon
type
=
"delete"
theme
=
"filled"
/><
/div
>
<
/div
>
<
/div
>
);
case
'img'
:
return
(
<
div
key
=
{
index
}
className
=
{
pageStyle
.
uploadimgbox
}
>
<
div
className
=
{
pageStyle
.
imgwrap
}
>
<
div
className
=
{
pageStyle
.
uploadimgwrap
}
>
<
img
alt
=
{
item
.
type
}
className
=
{
pageStyle
.
teacheruploadimg
}
src
=
{
imagify
(
item
.
value
)}
/></
div
>
<
div
className
=
{
pageStyle
.
imghide
}
>
<
span
title
=
"预览文件"
onClick
=
{()
=>
this
.
priviewImg
(
item
.
value
)}
><
Icon
style
=
{{
color
:
'#fff'
}}
type
=
"eye"
/>
预览
<
/span
>
<
/div
>
<
div
className
=
{
pageStyle
.
toolList
}
>
{
index
===
0
&&
<
div
aria
-
disabled
=
"true"
className
=
{
pageStyle
.
noup
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
>
0
&&
<
div
className
=
{
pageStyle
.
up
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'up'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
===
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
nodown
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
<
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
down
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'down'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
<
div
className
=
{
pageStyle
.
delete
}
onClick
=
{()
=>
deleteThemeImg
(
index
,
sort
)}
><
Icon
type
=
"delete"
theme
=
"filled"
/><
/div
>
<
/div
>
<
/div
>
<
/div
>
);
case
'voice'
:
return
(
<
div
key
=
{
index
}
className
=
{
pageStyle
.
uploadimgbox
}
>
<
div
className
=
{
pageStyle
.
imgwrap
}
>
<
audio
controls
=
"controls"
style
=
{{
width
:
'100%'
}}
src
=
{
audioorigin
(
item
.
value
)}
><
/audio
>
<
div
className
=
{
pageStyle
.
toolList
}
>
{
index
===
0
&&
<
div
aria
-
disabled
=
"true"
className
=
{
pageStyle
.
noup
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
>
0
&&
<
div
className
=
{
pageStyle
.
up
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'up'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
===
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
nodown
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
<
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
down
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'down'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
<
div
className
=
{
pageStyle
.
delete
}
onClick
=
{()
=>
deleteThemeImg
(
index
,
sort
)}
><
Icon
type
=
"delete"
theme
=
"filled"
/><
/div
>
<
/div
>
<
/div
>
<
/div
>
);
case
'video'
:
return
(
<
div
key
=
{
index
}
className
=
{
pageStyle
.
videowrap
}
>
<
video
controls
=
"controls"
className
=
{
pageStyle
.
videoPoster
}
src
=
{
ossVideofy
(
item
.
value
)}
/
>
<
div
className
=
{
pageStyle
.
toolList
}
>
{
index
===
0
&&
<
div
aria
-
disabled
=
"true"
className
=
{
pageStyle
.
noup
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
>
0
&&
<
div
className
=
{
pageStyle
.
up
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'up'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
===
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
nodown
}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
{
index
<
(
ele
.
content
.
length
-
1
)
&&
<
div
className
=
{
pageStyle
.
down
}
onClick
=
{()
=>
moveContent
(
index
,
sort
,
'down'
)}
><
img
src
=
{
upImg
}
alt
=
""
/>
<
/div>
}
<
div
className
=
{
pageStyle
.
delete
}
onClick
=
{()
=>
deleteThemeImg
(
index
,
sort
)}
><
Icon
type
=
"delete"
theme
=
"filled"
/><
/div
>
<
/div
>
<
/div
>
);
default
:
return
<
div
><
/div>
;
}
})
}
<
div
className
=
{
pageStyle
.
uploadflex
}
>
<
div
className
=
{
pageStyle
.
uploadimg
}
onClick
=
{()
=>
editorAddText
(
sort
)}
><
Icon
style
=
{{
marginRight
:
10
}}
type
=
"font-size"
/>
添加文字
<
/div
>
<
div
className
=
{
pageStyle
.
uploadimg
}
><
input
type
=
"file"
id
=
"uploadImg"
className
=
{
pageStyle
.
fileuploadinput
}
onChange
=
{
e
=>
editorUploadImg
(
e
,
sort
)}
accept
=
"image/*"
/><
Icon
style
=
{{
marginRight
:
10
}}
type
=
"picture"
/>
添加图片
<
/div
>
<
div
className
=
{
pageStyle
.
uploadimg
}
><
input
type
=
"file"
id
=
"uploadVoice"
className
=
{
pageStyle
.
fileuploadinput
}
onChange
=
{
e
=>
editorUploadVoice
(
e
,
sort
)}
accept
=
"audio/mp3"
/><
Icon
style
=
{{
marginRight
:
10
}}
type
=
"audio"
/>
添加录音
<
/div
>
<
div
className
=
{
pageStyle
.
uploadimg
}
><
input
type
=
"file"
id
=
"uploadVideo"
className
=
{
pageStyle
.
fileuploadinput
}
onChange
=
{
e
=>
editorUploadAudio
(
e
,
sort
)}
accept
=
"video/mp4,video/*"
/><
Icon
style
=
{{
marginRight
:
10
}}
type
=
"video-camera"
/>
添加视频
<
/div
>
<
/div
>
<
p
>
请上传视频小于
1
G
,支持
MP4
格式
<
/p
>
<
/div
>
);
})
}
<
/div
>
<
div
className
=
{
pageStyle
.
addPlate
}
onClick
=
{
editorAddPlate
}
>
添加版块
<
/div
>
<
Modal
visible
=
{
previewVisible
}
footer
=
{
null
}
onCancel
=
{
this
.
handleCancel
}
>
<
img
alt
=
"图片"
style
=
{{
width
:
'100%'
}}
src
=
{
imagify
(
previewImage
)}
/
>
<
/Modal
>
<
/div
>
);
}
}
ThemeEditor
.
propTypes
=
{
};
export
default
connect
()(
ThemeEditor
);
src/pages/newtheme/customsclock/components/ThemeEditor.less
0 → 100644
View file @
a096ee83
.textWrap {
width: 560px;
height: auto;
position: relative;
margin-bottom:10px;
:global {
.ant-input {
padding: 6px 15px 20px;
}
}
.sizeNumber {
position: absolute;
bottom: 8px;
right: 10px;
}
}
.editorwrap {
//width: 563px;
margin-top: 15px;
.videowrap {
width: 100%;
height: 200px;
position: relative;
margin-bottom: 10px;
.videoPoster {
width: 100%;
height: 100%;
}
}
.videowrap:hover {
cursor: pointer;
.videohide {
opacity: 1;
background-color: rgba(0,0,0,0.5);
transition: all .3s;
z-index: 1;
color: #fff;
}
}
.videohide {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
color: #fff;
z-index: -1;
a {
color: #fff;
}
}
.uploadimgbox {
display: flex;
align-items: flex-end;
margin-bottom: 18px;
flex-wrap: wrap;
.imgwrap {
width: 100%;
// height: 120px;
border-radius: 4px;
margin-right: 6px;
position: relative;
.uploadimgwrap {
width: 100%;
// height: 120px;
overflow: hidden;
}
}
.imgwrap:hover {
cursor: pointer;
.imghide {
opacity: 1;
background-color: rgba(0,0,0,0.5);
transition: all .3s;
z-index: 1;
color: #fff;
}
}
.imghide {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
color: #fff;
z-index: -1;
a {
color: #fff;
}
}
.teacheruploadimg {
object-fit: contain;
border-radius: 4px;
width: 100%;
}
.teacheruploadimg:nth-child(4n){
margin-right: 0;
}
}
}
.uploadflex {
display: flex;
align-items: center;
margin-top: 20px;
.uploadimg {
cursor: pointer;
width: 106px;
height: 32px;
line-height: 32px;
text-align: center;
border: 1px solid #D9D9D9;
border-radius: 4px;
color: rgba(0,0,0,0.65);
position: relative;
margin-right: 30px;
.fileuploadinput {
cursor: pointer;
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
opacity: 0;
left: 0;
top: 0;
}
}
}
.toolList {
position: absolute;
right: -30px;
top: 0;
width: 30px;
height: 90px;
display: flex;
flex-direction: column;
background-color: #D3D3D3;
opacity: 0;
border-radius: 2px;
z-index: -1;
div {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 14px;
cursor: pointer;
}
div>img {
width: 14px;
height: 14px;
}
.up:hover {
background-color: #1890FF;
}
.down,.nodown {
transform: rotate(180deg);
}
.nodown,.noup {
cursor: not-allowed;
}
.down:hover {
background-color: #1890FF;
}
.delete:hover {
background-color: #FF6060;
}
}
.textWrap:hover,.imgwrap:hover,.videowrap:hover {
.toolList {
opacity: 1;
z-index: 1;
}
}
.addPlate {
width: 214px;
height: 34px;
line-height: 34px;
text-align: center;
color: #65B8F4;
border: 1px solid #65B8F4;
border-radius: 17px;
margin: 40px auto 0;
cursor: pointer;
}
.plateWrap {
border:2px dashed rgba(208,208,208,1);
padding: 20px;
margin-bottom: 30px;
position: relative;
}
.plateDelete {
position: absolute;
right: -20px;
top: -25px;
font-size: 30px;
color: #FF6060;
cursor: pointer;
}
.progressWrap {
width: 300px;
height: 300px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #f1f1f1;
border-radius: 15px;
z-index: 9999;
&>p {
font-size: 18px;
margin-top: 30px;
color: #1e8bff;
}
}
\ No newline at end of file
src/pages/newtheme/jobclock/index.js
View file @
a096ee83
...
...
@@ -118,6 +118,14 @@ class JobClockForm extends React.Component {
payload
:
{
files
:
e
.
target
,
uploadtype
:
'uploadVideoJob'
,
progressCallBack
(
res
)
{
dispatch
({
type
:
'createtheme/updateState'
,
payload
:
{
progressRate
:
((
res
.
loaded
/
res
.
total
)
*
100
).
toFixed
(
0
),
},
});
},
},
});
}
...
...
@@ -205,6 +213,7 @@ class JobClockForm extends React.Component {
jobParams
,
editorText
,
isCopy
,
progressRate
,
}
=
this
.
props
;
const
formItemModalLineLayout
=
{
labelCol
:
{
...
...
@@ -469,6 +478,7 @@ class JobClockForm extends React.Component {
deleteThemeImg
=
{
this
.
deleteJobImg
}
moveContent
=
{
this
.
jobMoveContent
}
editorAddText
=
{
this
.
jobAddText
}
progressRate
=
{
progressRate
}
/
>
<
FormItem
{...
submitFormLayout
}
style
=
{{
marginTop
:
32
}}
>
<
Button
type
=
"primary"
htmlType
=
"submit"
loading
=
{
themeAddLoading
}
>
...
...
@@ -491,6 +501,7 @@ function mapStateToProps(state) {
jobParams
,
editorText
,
isCopy
,
progressRate
,
}
=
state
.
createtheme
;
return
{
themeAddLoading
,
...
...
@@ -498,6 +509,7 @@ function mapStateToProps(state) {
jobParams
,
editorText
,
isCopy
,
progressRate
,
};
}
export
default
connect
(
mapStateToProps
)(
JobClock
);
...
...
src/pages/thememgt/index.js
View file @
a096ee83
...
...
@@ -272,14 +272,12 @@ class ThemeMgt extends React.Component {
},
{
title
:
'打卡人数'
,
dataIndex
:
'clock_count'
,
dataIndex
:
'clock_
student_
count'
,
align
:
'center'
,
key
:
'
student_total
'
,
key
:
'
clock_student_count
'
,
render
:
(
text
,
record
,
index
)
=>
(
<
div
className
=
{
pageStyle
.
tablecell
}
>
{
record
.
subject_type
==
1
&&
record
.
student_total
}
{
record
.
subject_type
==
2
&&
record
.
student_total
}
{
record
.
subject_type
==
3
&&
record
.
class_students_count
}
{
text
}
<
/div
>
),
},
...
...
src/services/uploader.js
View file @
a096ee83
...
...
@@ -27,7 +27,7 @@ export function uploadVideoSignature({ type, token, schoolId }) {
});
}
export
function
uploadVideo
(
params
)
{
export
function
uploadVideo
(
params
,
progressCallback
)
{
const
{
OSSAccessKeyId
,
file
,
...
...
@@ -35,12 +35,17 @@ export function uploadVideo(params) {
policy
,
signature
,
url
,
callback
,
}
=
params
;
const
formData
=
new
FormData
();
formData
.
append
(
'key'
,
key
);
formData
.
append
(
'policy'
,
policy
);
formData
.
append
(
'OSSAccessKeyId'
,
OSSAccessKeyId
);
formData
.
append
(
'signature'
,
signature
);
if
(
callback
)
{
formData
.
append
(
'callback'
,
callback
);
}
formData
.
append
(
'success_action_status'
,
200
);
formData
.
append
(
'file'
,
file
);
return
request
({
url
:
params
.
url
,
...
...
@@ -50,6 +55,16 @@ export function uploadVideo(params) {
'Content-Type'
:
'multipart/form-data'
,
},
data
:
formData
,
retry
:
0
,
onUploadProgress
(
progressEvent
)
{
// 原生获取上传进度的事件
if
(
progressEvent
.
lengthComputable
)
{
// 属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
// 如果lengthComputable为false,就获取不到progressEvent.total和progressEvent.loaded
if
(
progressCallback
&&
(
typeof
progressCallback
==
'function'
))
{
progressCallback
(
progressEvent
);
}
}
},
});
}
export
function
uploadImageSignature
({
type
,
token
,
schoolId
})
{
...
...
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