feat(editor): 集成富文本编辑器并优化响应式布局
1. 添加wangEditor富文本编辑器替换原有简易编辑器 2. 新增编辑器相关CSS样式和功能按钮 3. 优化详情页和编辑页的响应式布局 4. 调整评论区域样式结构 5. 添加移动端适配样式
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -71,6 +71,7 @@
|
|||||||
padding: 40px 30px 35px;
|
padding: 40px 30px 35px;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: none;
|
display: none;
|
||||||
|
max-width: calc(100vw - 10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.coins-area .coins-box .fork {
|
.coins-area .coins-box .fork {
|
||||||
|
|||||||
128
css/details.css
128
css/details.css
@@ -1,6 +1,7 @@
|
|||||||
#details {
|
#details {
|
||||||
width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
min-width: 320px;
|
||||||
}
|
}
|
||||||
#details .matter {
|
#details .matter {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@@ -338,6 +339,7 @@
|
|||||||
}
|
}
|
||||||
#details .matter .matter-left .related .list .item .text {
|
#details .matter .matter-left .related .list .item .text {
|
||||||
width: 352px;
|
width: 352px;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
#details .matter .sidebar-box {
|
#details .matter .sidebar-box {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@@ -845,30 +847,29 @@
|
|||||||
border-top: 1px dotted #ebebeb;
|
border-top: 1px dotted #ebebeb;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header {
|
.answer-discuss .comments-box .comments-item .comments-header {
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 9px;
|
margin-bottom: 9px;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left {
|
.answer-discuss .comments-box .comments-item .comments-header {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-avatar {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-avatar {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-username {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-username {
|
||||||
color: #555;
|
color: #555;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-time {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-time {
|
||||||
color: #aaaaaa;
|
color: #aaaaaa;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-identity {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-identity {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #7f7f7f;
|
color: #7f7f7f;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
@@ -877,18 +878,19 @@
|
|||||||
border: 1px solid #d7d7d7;
|
border: 1px solid #d7d7d7;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box:hover .operate-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box:hover .operate-box {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .menu-icon {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .menu-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box {
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -903,13 +905,13 @@
|
|||||||
background-color: #f6f6f6;
|
background-color: #f6f6f6;
|
||||||
border: 1px solid #d7d7d7;
|
border: 1px solid #d7d7d7;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box .item {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box .item {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box .item:not(:last-of-type) {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box .item:not(:last-of-type) {
|
||||||
border-bottom: 1px solid #d7d7d7;
|
border-bottom: 1px solid #d7d7d7;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box::after {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 58px;
|
width: 58px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
@@ -918,7 +920,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .report-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .report-box {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 24px;
|
top: 24px;
|
||||||
@@ -932,7 +934,7 @@
|
|||||||
color: #7f7f7f;
|
color: #7f7f7f;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .report-box::after {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .report-box::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 58px;
|
width: 58px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
@@ -940,23 +942,23 @@
|
|||||||
top: -14px;
|
top: -14px;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .comment-icon {
|
.answer-discuss .comments-box .comments-item .comments-header .comment-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 13px;
|
height: 13px;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .like-box {
|
.answer-discuss .comments-box .comments-item .comments-header .like-box {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .like-box .like-icon {
|
.answer-discuss .comments-box .comments-item .comments-header .like-box .like-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .like-box .like-quantity {
|
.answer-discuss .comments-box .comments-item .comments-header .like-box .like-quantity {
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
.answer-discuss .comments-box .comments-item .comments-content {
|
.answer-discuss .comments-box .comments-item .comments-content {
|
||||||
@@ -1251,3 +1253,89 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
background-color: rgba(0, 0, 0, 0.20392157);
|
background-color: rgba(0, 0, 0, 0.20392157);
|
||||||
}
|
}
|
||||||
|
@media screen and (max-width: 850px) {
|
||||||
|
#details {
|
||||||
|
padding: 10px 10px 0;
|
||||||
|
}
|
||||||
|
#details .head-top {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#details .head-navigation {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .action-bar {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .action-bar .action-bar-item {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .related .related-head {
|
||||||
|
padding-left: 14px;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .related .list {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .related .list .item {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .related .list .item:not(:last-child) {
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
#details .matter .matter-left .related .list .item .text {
|
||||||
|
width: calc(100vw - 100px);
|
||||||
|
}
|
||||||
|
#details .matter .sidebar-box {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#details .answer-discuss {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
#details .answer-discuss .input-box .picture-box {
|
||||||
|
width: calc(100vw - 68px);
|
||||||
|
}
|
||||||
|
#details .answer-discuss .input-box .bottom .operate .item .emoji-box {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
transform: translateX(0);
|
||||||
|
width: 100vw;
|
||||||
|
height: 300px;
|
||||||
|
top: auto;
|
||||||
|
overflow: auto;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
#details .answer-discuss .input-box .bottom .operate .item .emoji-box::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#details .answer-discuss .comments-box .input-box .picture-box {
|
||||||
|
width: calc(100vw - 88px);
|
||||||
|
}
|
||||||
|
#details .answer-discuss .comments-box .comments-item .comments-header {
|
||||||
|
justify-content: inherit;
|
||||||
|
}
|
||||||
|
#details .answer-discuss .comments-box .comments-item .comments-header .menu-box {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
#details .answer-discuss .comments-box .comments-item .child-comments .input-box .picture-box {
|
||||||
|
width: calc(100vw - 128px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
#details .answer-discuss .comments-box .comments-item .comments-header {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
#details .answer-discuss .comments-box .comments-item .comments-header .comments-title {
|
||||||
|
height: 14px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 450px) {
|
||||||
|
#details .answer-discuss .comments-box .comments-item .comments-header .comment-icon,
|
||||||
|
#details .answer-discuss .comments-box .comments-item .comments-header .like-box {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
188
css/details.less
188
css/details.less
@@ -1,6 +1,8 @@
|
|||||||
#details {
|
#details {
|
||||||
width: 1200px;
|
// width: 1200px;
|
||||||
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
min-width: 320px;
|
||||||
|
|
||||||
.matter {
|
.matter {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@@ -204,7 +206,7 @@
|
|||||||
video {
|
video {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif;
|
||||||
font-weight: 650;
|
font-weight: 650;
|
||||||
@@ -393,6 +395,7 @@
|
|||||||
|
|
||||||
.text {
|
.text {
|
||||||
width: 352px;
|
width: 352px;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -994,16 +997,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header {
|
.answer-discuss .comments-box .comments-item .comments-header {
|
||||||
justify-content: space-between;
|
// justify-content: space-between;
|
||||||
margin-bottom: 9px;
|
margin-bottom: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left {
|
.answer-discuss .comments-box .comments-item .comments-header {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-avatar {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-avatar {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
@@ -1011,18 +1014,18 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-username {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-username {
|
||||||
color: #555;
|
color: #555;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-time {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-time {
|
||||||
color: #aaaaaa;
|
color: #aaaaaa;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-left .comments-identity {
|
.answer-discuss .comments-box .comments-item .comments-header .comments-identity {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #7f7f7f;
|
color: #7f7f7f;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
@@ -1032,21 +1035,22 @@
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box:hover .operate-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box:hover .operate-box {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .menu-icon {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .menu-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box {
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -1062,15 +1066,15 @@
|
|||||||
border: 1px solid rgba(215, 215, 215, 1);
|
border: 1px solid rgba(215, 215, 215, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box .item {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box .item {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box .item:not(:last-of-type) {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box .item:not(:last-of-type) {
|
||||||
border-bottom: 1px solid rgba(215, 215, 215, 1);
|
border-bottom: 1px solid rgba(215, 215, 215, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .operate-box::after {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .operate-box::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 58px;
|
width: 58px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
@@ -1080,7 +1084,7 @@
|
|||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .report-box {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .report-box {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 24px;
|
top: 24px;
|
||||||
@@ -1095,7 +1099,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .menu-box .report-box::after {
|
.answer-discuss .comments-box .comments-item .comments-header .menu-box .report-box::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 58px;
|
width: 58px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
@@ -1104,26 +1108,26 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .comment-icon {
|
.answer-discuss .comments-box .comments-item .comments-header .comment-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 13px;
|
height: 13px;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .like-box {
|
.answer-discuss .comments-box .comments-item .comments-header .like-box {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .like-box .like-icon {
|
.answer-discuss .comments-box .comments-item .comments-header .like-box .like-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .comments-box .comments-item .comments-header .comments-header-right .like-box .like-quantity {
|
.answer-discuss .comments-box .comments-item .comments-header .like-box .like-quantity {
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1458,3 +1462,145 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
background-color: rgba(0, 0, 0, 0.20392157);
|
background-color: rgba(0, 0, 0, 0.20392157);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 媒体查询 最大宽度 850px 时
|
||||||
|
@media screen and (max-width: 850px) {
|
||||||
|
#details {
|
||||||
|
padding: 10px 10px 0;
|
||||||
|
.head-top {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head-navigation {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matter {
|
||||||
|
.matter-left {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
.action-bar {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 0 !important;
|
||||||
|
|
||||||
|
.action-bar-item {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.related {
|
||||||
|
.related-head {
|
||||||
|
padding-left: 14px;
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
padding: 14px;
|
||||||
|
.item {
|
||||||
|
width: 100% !important;
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
width: calc(100vw - 100px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sidebar-box {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.answer-discuss {
|
||||||
|
padding: 15px;
|
||||||
|
|
||||||
|
.input-box {
|
||||||
|
.picture-box {
|
||||||
|
width: calc(100vw - 68px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
.operate {
|
||||||
|
.item {
|
||||||
|
.emoji-box {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
transform: translateX(0);
|
||||||
|
width: 100vw;
|
||||||
|
height: 300px;
|
||||||
|
top: auto;
|
||||||
|
overflow: auto;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments-box {
|
||||||
|
.input-box {
|
||||||
|
.picture-box {
|
||||||
|
width: calc(100vw - 88px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments-item {
|
||||||
|
.comments-header {
|
||||||
|
justify-content: inherit;
|
||||||
|
|
||||||
|
.menu-box {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.child-comments {
|
||||||
|
.input-box {
|
||||||
|
.picture-box {
|
||||||
|
width: calc(100vw - 128px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
#details {
|
||||||
|
.answer-discuss {
|
||||||
|
.comments-box {
|
||||||
|
.comments-item {
|
||||||
|
.comments-header {
|
||||||
|
font-size: 12px;
|
||||||
|
.comments-title {
|
||||||
|
height: 14px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 450px) {
|
||||||
|
#details {
|
||||||
|
.answer-discuss {
|
||||||
|
.comments-box {
|
||||||
|
.comments-item {
|
||||||
|
.comments-header {
|
||||||
|
.comment-icon,
|
||||||
|
.like-box {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
27
css/editor.css
Normal file
27
css/editor.css
Normal file
File diff suppressed because one or more lines are too long
121
details.html
121
details.html
@@ -18,7 +18,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<sign-in-box></sign-in-box>
|
<sign-in-box></sign-in-box>
|
||||||
<div class="container" id="details" v-cloak>
|
<div class="container" id="details" v-cloak>
|
||||||
<div class="templateValue" ref="uniqidRef">fi88yrHXiDSj</div>
|
<div class="templateValue" ref="uniqidRef">qXi0yrL189WW</div>
|
||||||
|
|
||||||
<div class="head-top flexacenter">
|
<div class="head-top flexacenter">
|
||||||
<img class="logo" src="https://oss.gter.net/logo" alt="" />
|
<img class="logo" src="https://oss.gter.net/logo" alt="" />
|
||||||
@@ -211,41 +211,38 @@
|
|||||||
<div class="comments-box" v-if="commentTotalCount != 0">
|
<div class="comments-box" v-if="commentTotalCount != 0">
|
||||||
<div class="comments-item" v-for="(item, index) in commentList" :key="index">
|
<div class="comments-item" v-for="(item, index) in commentList" :key="index">
|
||||||
<div class="comments-header flexacenter">
|
<div class="comments-header flexacenter">
|
||||||
<div class="comments-header-left flexacenter">
|
<img class="comments-avatar" @click="openUserInfo(index)" :src="item.avatar || item.user['avatar']" />
|
||||||
<img class="comments-avatar" @click="openUserInfo(index)" :src="item.avatar || item.user['avatar']" />
|
<div class="comments-username" @click="openUserInfo(index)">{{ item.nickname || item.user["nickname"] || "匿名用户" }}</div>
|
||||||
<div class="comments-username" @click="openUserInfo(index)">{{ item.nickname || item.user["nickname"] || "匿名用户" }}</div>
|
<div class="comments-time">{{ item["timestamp"] }}</div>
|
||||||
<div class="comments-time">{{ item["timestamp"] }}</div>
|
<div class="comments-identity" v-if="item['isauthor'] == 1">作者</div>
|
||||||
<div class="comments-identity" v-if="item['isauthor'] == 1">作者</div>
|
<img class="comments-title" v-if="item.groupimage || item?.user?.groupimage" :src="item.groupimage || item?.user?.groupimage" :alt="item?.user?.grouptitle" style="height: 18px" />
|
||||||
<img class="comments-title" v-if="item.groupimage || item?.user?.groupimage" :src="item.groupimage || item?.user?.groupimage" :alt="item?.user?.grouptitle" style="height: 18px" />
|
|
||||||
|
|
||||||
<div class="avatar-box flexflex" v-if="item['avatarState']">
|
<div class="avatar-box flexflex" v-if="item['avatarState']">
|
||||||
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(item.uin || item.user['uin'])">
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(item.uin || item.user['uin'])">
|
||||||
<img class="avatar-icon" src="./img/send-messages-icon.png" />
|
<img class="avatar-icon" src="./img/send-messages-icon.png" />
|
||||||
发送信息
|
发送信息
|
||||||
</a>
|
</a>
|
||||||
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(item.uin || item.user['uin'])">
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(item.uin || item.user['uin'])">
|
||||||
<img class="avatar-icon" src="./img/homepage-icon.png" />
|
<img class="avatar-icon" src="./img/homepage-icon.png" />
|
||||||
TA的主页
|
TA的主页
|
||||||
</a>
|
</a>
|
||||||
<div class="avatar-mask" @click="closeUserInfo(index)"></div>
|
<div class="avatar-mask" @click="closeUserInfo(index)"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-box flexacenter">
|
||||||
|
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
||||||
|
<!-- <div class="report-box flexcenter">举报</div> -->
|
||||||
|
<div class="operate-box">
|
||||||
|
<div class="item flexcenter" @click="commentReport(item['token'])">举报</div>
|
||||||
|
<div class="item flexcenter" v-if="permissions.includes('comment.edit')" @click="openEdit(item['token'], index)">编辑</div>
|
||||||
|
<div class="item flexcenter" v-if="permissions.includes('comment.delete')" @click="commentDelete(item['token'], index)">删除</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="comments-header-right flexacenter">
|
<img class="comment-icon" @click="openAnswerCommentsChild(index)" src="./img/comment-icon-gray.svg" />
|
||||||
<div class="menu-box flexacenter">
|
<div class="flexacenter like-box" @click="operateAnswerCommentsLike(item.token, index)">
|
||||||
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
<img class="like-icon" v-if="item['islike'] == 0" src="./img/like-icon-gray.png" />
|
||||||
<!-- <div class="report-box flexcenter">举报</div> -->
|
<img class="like-icon" v-else src="./img/like-red-pitch.png" />
|
||||||
<div class="operate-box">
|
<div class="like-quantity">{{ item["likenum"] || "" }}</div>
|
||||||
<div class="item flexcenter" @click="commentReport(item['token'])">举报</div>
|
|
||||||
<div class="item flexcenter" v-if="permissions.includes('comment.edit')" @click="openEdit(item['token'], index)">编辑</div>
|
|
||||||
<div class="item flexcenter" v-if="permissions.includes('comment.delete')" @click="commentDelete(item['token'], index)">删除</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<img class="comment-icon" @click="openAnswerCommentsChild(index)" src="./img/comment-icon-gray.svg" />
|
|
||||||
<div class="flexacenter like-box" @click="operateAnswerCommentsLike(item.token, index)">
|
|
||||||
<img class="like-icon" v-if="item['islike'] == 0" src="./img/like-icon-gray.png" />
|
|
||||||
<img class="like-icon" v-else src="./img/like-red-pitch.png" />
|
|
||||||
<div class="like-quantity">{{ item["likenum"] || "" }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="comments-content">
|
<div class="comments-content">
|
||||||
@@ -285,39 +282,35 @@
|
|||||||
<div class="child-comments" v-if="item['child'].length != 0">
|
<div class="child-comments" v-if="item['child'].length != 0">
|
||||||
<div class="comments-item" v-for="(ite, i) in item['child']" :key="ite.id">
|
<div class="comments-item" v-for="(ite, i) in item['child']" :key="ite.id">
|
||||||
<div class="comments-header flexacenter">
|
<div class="comments-header flexacenter">
|
||||||
<div class="comments-header-left flexacenter">
|
<img class="comments-avatar" @click="openUserInfo(index, i)" :src="ite.avatar || ite.user['avatar']" />
|
||||||
<img class="comments-avatar" @click="openUserInfo(index, i)" :src="ite.avatar || ite.user['avatar']" />
|
<div class="comments-username" @click="openUserInfo(index, i)">{{ ite.nickname || ite.user["nickname"] || "匿名用户" }}</div>
|
||||||
<div class="comments-username" @click="openUserInfo(index, i)">{{ ite.nickname || ite.user["nickname"] || "匿名用户" }}</div>
|
<div class="comments-time">{{ ite["timestamp"] }}</div>
|
||||||
<div class="comments-time">{{ ite["timestamp"] }}</div>
|
<div class="comments-identity" v-if="ite['isauthor'] == 1">作者</div>
|
||||||
<div class="comments-identity" v-if="ite['isauthor'] == 1">作者</div>
|
<img class="comments-title" v-if="ite.groupimage || ite.user?.groupimage" :src="ite.groupimage || ite.user?.groupimage" :alt="ite?.user?.grouptitle" style="height: 18px" />
|
||||||
<img class="comments-title" v-if="ite.groupimage || ite.user?.groupimage" :src="ite.groupimage || ite.user?.groupimage" :alt="ite?.user?.grouptitle" style="height: 18px" />
|
<div class="avatar-box flexflex" v-if="ite['avatarState']">
|
||||||
<div class="avatar-box flexflex" v-if="ite['avatarState']">
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(ite.uin || ite.user['uin'])">
|
||||||
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(ite.uin || ite.user['uin'])">
|
<img class="avatar-icon" src="./img/send-messages-icon.png" />
|
||||||
<img class="avatar-icon" src="./img/send-messages-icon.png" />
|
发送信息
|
||||||
发送信息
|
</a>
|
||||||
</a>
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(ite.uin || ite.user['uin'])">
|
||||||
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(ite.uin || ite.user['uin'])">
|
<img class="avatar-icon" src="./img/homepage-icon.png" />
|
||||||
<img class="avatar-icon" src="./img/homepage-icon.png" />
|
TA的主页
|
||||||
TA的主页
|
</a>
|
||||||
</a>
|
<div class="avatar-mask" @click="closeUserInfo(index, i)"></div>
|
||||||
<div class="avatar-mask" @click="closeUserInfo(index, i)"></div>
|
</div>
|
||||||
|
<div class="menu-box flexacenter">
|
||||||
|
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
||||||
|
<div class="operate-box">
|
||||||
|
<div class="item flexcenter" @click="commentReport(ite['token'])">举报</div>
|
||||||
|
<div class="item flexcenter" v-if="permissions.includes('comment.edit')" @click="openEdit(ite['token'], index, i)">编辑</div>
|
||||||
|
<div class="item flexcenter" v-if="permissions.includes('comment.delete')" @click="commentDelete(ite['token'], index, i)">删除</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="comments-header-right flexacenter">
|
<img class="comment-icon" @click="openAnswerCommentsChild(index, i)" src="./img/comment-icon-gray.svg" />
|
||||||
<div class="menu-box flexacenter">
|
<div class="flexacenter like-box" @click="operateAnswerCommentsLike(ite.token, index, i)">
|
||||||
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
<img class="like-icon" v-if="ite['islike'] == 0" src="./img/like-icon-gray.png" />
|
||||||
<div class="operate-box">
|
<img class="like-icon" v-else src="./img/like-red-pitch.png" />
|
||||||
<div class="item flexcenter" @click="commentReport(ite['token'])">举报</div>
|
<div class="like-quantity">{{ ite["likenum"] || "" }}</div>
|
||||||
<div class="item flexcenter" v-if="permissions.includes('comment.edit')" @click="openEdit(ite['token'], index, i)">编辑</div>
|
|
||||||
<div class="item flexcenter" v-if="permissions.includes('comment.delete')" @click="commentDelete(ite['token'], index, i)">删除</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<img class="comment-icon" @click="openAnswerCommentsChild(index, i)" src="./img/comment-icon-gray.svg" />
|
|
||||||
<div class="flexacenter like-box" @click="operateAnswerCommentsLike(ite.token, index, i)">
|
|
||||||
<img class="like-icon" v-if="ite['islike'] == 0" src="./img/like-icon-gray.png" />
|
|
||||||
<img class="like-icon" v-else src="./img/like-red-pitch.png" />
|
|
||||||
<div class="like-quantity">{{ ite["likenum"] || "" }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="comments-content">
|
<div class="comments-content">
|
||||||
|
|||||||
130
edit.html
130
edit.html
@@ -7,21 +7,40 @@
|
|||||||
<title>发布帖子 - 轻论坛</title>
|
<title>发布帖子 - 轻论坛</title>
|
||||||
<link rel="stylesheet" href="./css/public.css" />
|
<link rel="stylesheet" href="./css/public.css" />
|
||||||
<link rel="stylesheet" href="./css/edit.css" />
|
<link rel="stylesheet" href="./css/edit.css" />
|
||||||
|
<link href="./css/editor.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script src="./js/vue.global.js"></script>
|
<script src="./js/vue.global.js"></script>
|
||||||
<style>
|
<style>
|
||||||
[v-cloak] {
|
[v-cloak] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#editor—wrapper {
|
||||||
|
/* border: 1px solid #ccc; */
|
||||||
|
z-index: 100;
|
||||||
|
/* 按需定义 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar-container {
|
||||||
|
/* border-bottom: 1px solid #ccc; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor-container {
|
||||||
|
min-height: 509px;
|
||||||
|
max-height: 80vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="./js/editor.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container" id="edit" v-cloak>
|
<div class="container" id="edit" v-cloak>
|
||||||
<div class="edit-head flexacenter">
|
<div class="edit-head flexacenter">
|
||||||
<div class="edit-head-container flexacenter">
|
<div class="edit-head-container flexacenter">
|
||||||
<a class="" href="/" target="_blank">
|
<a class="" href="/" target="_blank"><img class="icon" src="{@/img/edit-logo-icon.png}" /></a>
|
||||||
<img class="icon" src="{@/img/edit-logo-icon.png}" />
|
|
||||||
</a>
|
|
||||||
<div class="dot"></div>
|
<div class="dot"></div>
|
||||||
<div class="title">发帖</div>
|
<div class="title">发帖</div>
|
||||||
<div class="hint">发帖奖励 3 个寄托币/篇,每天最高奖励3篇</div>
|
<div class="hint">发帖奖励 3 个寄托币/篇,每天最高奖励3篇</div>
|
||||||
@@ -32,63 +51,68 @@
|
|||||||
<div class="edit-container">
|
<div class="edit-container">
|
||||||
<!-- 标题输入 -->
|
<!-- 标题输入 -->
|
||||||
<div class="title-box">
|
<div class="title-box">
|
||||||
<input class="title-input" type="title" placeholder="输入标题(非必填)" v-model="info.title"
|
<input class="title-input" type="title" placeholder="输入标题(非必填)" v-model="info.title" :maxlength="titleLength" />
|
||||||
:maxlength="titleLength" />
|
|
||||||
<div class="sum">{{ info?.title?.length ? titleLength - info?.title?.length : titleLength }}</div>
|
<div class="sum">{{ info?.title?.length ? titleLength - info?.title?.length : titleLength }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="editor—wrapper">
|
||||||
|
|
||||||
<!-- 工具栏 -->
|
<!-- 工具栏 -->
|
||||||
<div class="editor-toolbar flexacenter">
|
<div id="toolbar-container" class="editor-toolbar flexacenter">
|
||||||
<div class="toolbar-item flexacenter h2" :class="{'pitch': isPTitle}" @click="paragraphTitle">
|
<div class="toolbar-item flexacenter h2" :class="{'pitch': isPTitle}" @click="paragraphTitle">
|
||||||
<img class="icon" src="{@/img/t-icon.png}" alt="段落标题" />
|
<img class="icon" src="{@/img/t-icon.png}" alt="段落标题" />
|
||||||
<span>段落标题</span>
|
<span>段落标题</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-item flexacenter">
|
<div class="toolbar-item flexacenter">
|
||||||
<img class="icon" src="{@/img/img-icon.png}" alt="图片" />
|
<img class="icon" src="{@/img/img-icon.png}" alt="图片" />
|
||||||
<span>图片</span>
|
<span>图片</span>
|
||||||
<input class="file" type="file" @change="insertImage" accept=".png, .jpg, .jpeg" />
|
<input class="file" type="file" @change="insertImage" accept=".png, .jpg, .jpeg" />
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-item flexacenter">
|
<div class="toolbar-item flexacenter">
|
||||||
<img class="icon" src="{@/img/video-icon.png}" alt="视频" />
|
<img class="icon" src="{@/img/video-icon.png}" alt="视频" />
|
||||||
<span>视频</span>
|
<span>视频</span>
|
||||||
<input class="file" type="file" @change="insertVideo" accept=".mp4, .avi, .mov" />
|
<input class="file" type="file" @change="insertVideo" accept=".mp4, .avi, .mov" />
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-item flexacenter expression" :class="{'pitch': emojiState}" @click="openEmoji">
|
<div class="toolbar-item flexacenter expression" :class="{'pitch': emojiState}" @click="openEmoji">
|
||||||
<img class="icon" src="{@/img/smiling-face-round-black.png}" alt="表情" />
|
<img class="icon" src="{@/img/smiling-face-round-black.png}" alt="表情" />
|
||||||
<span>表情</span>
|
<span>表情</span>
|
||||||
<div class="emoji-box-mask" @click.stop="closeEmoji"></div>
|
<div class="emoji-box-mask" @click.stop="closeEmoji"></div>
|
||||||
<div class="emoji-box">
|
<div class="emoji-box">
|
||||||
<div class="emoji-icon" v-for="emoji in optionEmoji" :key="emoji"
|
<div class="emoji-icon" v-for="emoji in optionEmoji" :key="emoji" @click.stop="selectEmoji(emoji)">{{ emoji }}</div>
|
||||||
@click.stop="selectEmoji(emoji)">{{ emoji }}</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="toolbar-item flexacenter link" :class="{'pitch': linkState}" @click="openLink">
|
||||||
<div class="toolbar-item flexacenter link" :class="{'pitch': linkState}" @click="openLink">
|
<img class="icon" src="{@/img/link-icon.png}" alt="链接" />
|
||||||
<img class="icon" src="{@/img/link-icon.png}" alt="链接" />
|
<span>链接</span>
|
||||||
<span>链接</span>
|
<div class="link-box-mask" @click.stop="closeLink"></div>
|
||||||
<div class="link-box-mask" @click.stop="closeLink"></div>
|
<div class="link-box flexflex" @click.stop="linkClick">
|
||||||
<div class="link-box flexflex" @click.stop="linkClick">
|
<div class="item flexflex">
|
||||||
<div class="item flexflex">
|
<div class="name">请输入链接地址:</div>
|
||||||
<div class="name">请输入链接地址:</div>
|
<input class="input" type="text" v-model="linkUrl" />
|
||||||
<input class="input" type="text" v-model="linkUrl" />
|
</div>
|
||||||
</div>
|
<div class="item flexflex">
|
||||||
<div class="item flexflex">
|
<div class="name">请输入链接文字:</div>
|
||||||
<div class="name">请输入链接文字:</div>
|
<input class="input" type="text" v-model="linkText" />
|
||||||
<input class="input" type="text" v-model="linkText" />
|
</div>
|
||||||
</div>
|
<div class="btn flexcenter" @click.stop="insertLink">OK</div>
|
||||||
<div class="btn flexcenter" @click.stop="insertLink">OK</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="toolbar-item flexacenter expression" :class="{'pitch': emojiState}" @click="overstriking">
|
||||||
|
<img class="icon" src="{@/img/overstriking-icon.png}" alt="加粗" />
|
||||||
|
<span>加粗</span>
|
||||||
|
<div class="emoji-box-mask" @click.stop="closeEmoji"></div>
|
||||||
|
<div class="emoji-box">
|
||||||
|
<div class="emoji-icon" v-for="emoji in optionEmoji" :key="emoji" @click.stop="selectEmoji(emoji)">{{ emoji }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <div id="toolbar-container"></div> -->
|
||||||
|
<div id="editor-container"><!-- 编辑器 --></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 内容编辑区 -->
|
<!-- 内容编辑区 -->
|
||||||
<div class="content-input" id="editor" contenteditable="true" :class="{ 'empty': isEmpty }"
|
<!-- <div class="content-input" id="editor" contenteditable="true" :class="{ 'empty': isEmpty }" placeholder="输入正文" ref="editorRef" @input="onEditorInput" @focus="onEditorFocus" @blur="onEditorBlur" v-html="info.content" @click="handleClick"></div> -->
|
||||||
placeholder="输入正文" ref="editorRef" @input="onEditorInput" @focus="onEditorFocus" @blur="onEditorBlur"
|
|
||||||
v-html="info.content" @click="handleClick"></div>
|
|
||||||
|
|
||||||
<!-- 标签选择 -->
|
|
||||||
<!-- <div class="tags-list flexacenter">
|
|
||||||
<div class="tag-item" v-for="item in tagList" :key="item.tagId" @click="insertLabel(item.tagId)">#{{ item.title }}</div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<div class="action-buttons flexacenter">
|
<div class="action-buttons flexacenter">
|
||||||
|
|||||||
BIN
img/between -icon.png
Normal file
BIN
img/between -icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 261 B |
BIN
img/overstriking-icon.png
Normal file
BIN
img/overstriking-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -15,9 +15,6 @@ const appSectionIndex = createApp({
|
|||||||
setup() {
|
setup() {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getUserInfoWin();
|
getUserInfoWin();
|
||||||
setTimeout(() => {
|
|
||||||
SignInComponent.initComponent();
|
|
||||||
}, 3000);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let isLogin = ref(false);
|
let isLogin = ref(false);
|
||||||
|
|||||||
170
js/edit.js
170
js/edit.js
@@ -1,6 +1,8 @@
|
|||||||
// 简单版本的论坛编辑器,确保图片插入功能正常
|
// 简单版本的论坛编辑器,确保图片插入功能正常
|
||||||
const { createApp, ref, computed, onMounted, nextTick, onUnmounted } = Vue;
|
const { createApp, ref, computed, onMounted, nextTick, onUnmounted } = Vue;
|
||||||
import { headTop } from "../component/head-top/head-top.js";
|
import { headTop } from "../component/head-top/head-top.js";
|
||||||
|
const { createEditor, createToolbar } = window.wangEditor;
|
||||||
|
console.log("createEditor", createEditor);
|
||||||
|
|
||||||
const editApp = createApp({
|
const editApp = createApp({
|
||||||
setup() {
|
setup() {
|
||||||
@@ -12,11 +14,9 @@ const editApp = createApp({
|
|||||||
uniqid.value = params.uniqid || "";
|
uniqid.value = params.uniqid || "";
|
||||||
|
|
||||||
getUserInfoWin();
|
getUserInfoWin();
|
||||||
|
checkWConfig();
|
||||||
|
|
||||||
cUpload();
|
cUpload();
|
||||||
init();
|
|
||||||
|
|
||||||
checkWConfig();
|
|
||||||
|
|
||||||
// 添加selectionchange事件监听,当鼠标选中区域内容时更新lastSelection
|
// 添加selectionchange事件监听,当鼠标选中区域内容时更新lastSelection
|
||||||
document.addEventListener("selectionchange", handleSelectionChange);
|
document.addEventListener("selectionchange", handleSelectionChange);
|
||||||
@@ -107,6 +107,10 @@ const editApp = createApp({
|
|||||||
ajaxGet(`/v2/api/config/upload?type=topic`).then((res) => {
|
ajaxGet(`/v2/api/config/upload?type=topic`).then((res) => {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
uConfigData = data;
|
uConfigData = data;
|
||||||
|
|
||||||
|
console.log("uConfigData", uConfigData);
|
||||||
|
|
||||||
|
init();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,15 +136,153 @@ const editApp = createApp({
|
|||||||
info.value = infoTarget;
|
info.value = infoTarget;
|
||||||
token.value = data.token;
|
token.value = data.token;
|
||||||
|
|
||||||
nextTick(() => {
|
// nextTick(() => {
|
||||||
judgeIsEmpty();
|
// judgeIsEmpty();
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
initEditor();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("err", err);
|
console.log("err", err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let editor = null;
|
||||||
|
|
||||||
|
const initEditor = () => {
|
||||||
|
let infoTarget = info.value || {};
|
||||||
|
|
||||||
|
console.log("infoTarget", infoTarget);
|
||||||
|
|
||||||
|
const editorConfig = {
|
||||||
|
placeholder: "Type here...",
|
||||||
|
enabledMenus: [],
|
||||||
|
MENU_CONF: {
|
||||||
|
["emotion"]: {
|
||||||
|
emotions: optionEmoji.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
["uploadImage"]: {
|
||||||
|
server: uConfigData.url,
|
||||||
|
|
||||||
|
// form-data fieldName ,默认值 'wangeditor-uploaded-image'
|
||||||
|
fieldName: uConfigData.requestName,
|
||||||
|
|
||||||
|
// 单个文件的最大体积限制,默认为 2M
|
||||||
|
maxFileSize: maxSize, // 1M
|
||||||
|
|
||||||
|
// 最多可上传几个文件,默认为 100
|
||||||
|
maxNumberOfFiles: imageLength,
|
||||||
|
|
||||||
|
// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
|
||||||
|
allowedFileTypes: ["image/*", ".png", ".jpg", ".jpeg"],
|
||||||
|
|
||||||
|
// 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
|
||||||
|
meta: { ...uConfigData.params },
|
||||||
|
|
||||||
|
// 将 meta 拼接到 url 参数中,默认 false
|
||||||
|
metaWithUrl: false,
|
||||||
|
|
||||||
|
// 自定义增加 http header
|
||||||
|
headers: { accept: "application/json, text/plain, */*", ...uConfigData.headers },
|
||||||
|
|
||||||
|
// 跨域是否传递 cookie ,默认为 false
|
||||||
|
withCredentials: true,
|
||||||
|
|
||||||
|
// 超时时间,默认为 10 秒
|
||||||
|
|
||||||
|
async customUpload(file, insertFn) {
|
||||||
|
try {
|
||||||
|
let config = uConfigData;
|
||||||
|
// 1. 构造 FormData(包含你的接口所需字段)
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append(config.requestName, file); // 文件数据
|
||||||
|
formData.append("name", file.name); // 文件名
|
||||||
|
formData.append("type", "image"); // 文件名
|
||||||
|
formData.append("data", config.params.data); // 文件名
|
||||||
|
|
||||||
|
ajax(config.url, formData).then((res) => {
|
||||||
|
const data = res.data;
|
||||||
|
insertFn(data.url); // 传入图片的可访问 URL
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("上传出错:", err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 4. 链接菜单:显式启用(默认启用,补充配置防止被过滤)
|
||||||
|
link: {
|
||||||
|
disabled: false, // 确保不禁用
|
||||||
|
showTarget: true, // 显示「是否新窗口打开」选项
|
||||||
|
showRel: true, // 显示「rel 属性」选项
|
||||||
|
},
|
||||||
|
// 5. 对齐菜单:显式启用(默认启用,兜底配置)
|
||||||
|
justify: {
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
onChange(editor) {
|
||||||
|
const html = editor.getHtml();
|
||||||
|
console.log("editor content", html);
|
||||||
|
// 也可以同步到 <textarea>
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
editor = createEditor({
|
||||||
|
selector: "#editor-container",
|
||||||
|
html: "<p><br>555</p>",
|
||||||
|
config: editorConfig,
|
||||||
|
mode: "default",
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("editor", editor);
|
||||||
|
editor.addMark("bold", true); // 加粗
|
||||||
|
}, 1000);
|
||||||
|
// const toolbar = DomEditor.getToolbar(editor)
|
||||||
|
|
||||||
|
const toolbarConfig = {
|
||||||
|
// toolbarKeys: ["bold", "italic", "list"],
|
||||||
|
toolbarKeys: [
|
||||||
|
"headerSelect", // 标题
|
||||||
|
"bold", // 粗体
|
||||||
|
"italic", // 斜体
|
||||||
|
// "justify", // 对齐方式
|
||||||
|
{
|
||||||
|
key: "justifyCenter",
|
||||||
|
title: "对齐",
|
||||||
|
iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
|
||||||
|
menuKeys: ["justifyLeft", "justifyRight", "justifyCenter", "justifyJustify"],
|
||||||
|
},
|
||||||
|
"emotion", // 表情
|
||||||
|
"insertLink", // 插入链接
|
||||||
|
"uploadImage", // 插入图片
|
||||||
|
"uploadVideo", // 插入视频
|
||||||
|
"undo", // 撤销
|
||||||
|
"redo", // 重做
|
||||||
|
"fullScreen", // 全屏
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const toolbar = createToolbar({
|
||||||
|
editor,
|
||||||
|
selector: "#toolbar-container",
|
||||||
|
config: toolbarConfig,
|
||||||
|
mode: "default",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("toolbar", toolbar);
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
// const el = document.querySelector("#toolbar-container");
|
||||||
|
// if (el && el.children.length === 0) {
|
||||||
|
// createToolbar({ editor, selector: "#toolbar-container", config: toolbarConfig, mode: "default" });
|
||||||
|
// }
|
||||||
|
// }, 0);
|
||||||
|
};
|
||||||
|
|
||||||
const restoreHtml = (formattedText, attachments) => {
|
const restoreHtml = (formattedText, attachments) => {
|
||||||
const imageList = attachments?.images || [];
|
const imageList = attachments?.images || [];
|
||||||
|
|
||||||
@@ -196,7 +338,7 @@ const editApp = createApp({
|
|||||||
html = html.replace(/(<span class="blue">[^<]+<\/span>)\s+/gi, '$1 <span class="fill"></span> ');
|
html = html.replace(/(<span class="blue">[^<]+<\/span>)\s+/gi, '$1 <span class="fill"></span> ');
|
||||||
|
|
||||||
// 7. 清理多余的<br>标签
|
// 7. 清理多余的<br>标签
|
||||||
html = html.replace(/<br><br>/g, "<br>");
|
// html = html.replace(/<br><br>/g, "<br>");
|
||||||
|
|
||||||
imageList.forEach((element) => {
|
imageList.forEach((element) => {
|
||||||
html += `<img src="${element.url}" data-aid="${element.aid}"><br/>`;
|
html += `<img src="${element.url}" data-aid="${element.aid}"><br/>`;
|
||||||
@@ -218,6 +360,7 @@ const editApp = createApp({
|
|||||||
const editorRef = ref(null);
|
const editorRef = ref(null);
|
||||||
|
|
||||||
const focusLastNode = () => {
|
const focusLastNode = () => {
|
||||||
|
return;
|
||||||
const newRange = document.createRange();
|
const newRange = document.createRange();
|
||||||
const textNode = document.createTextNode("");
|
const textNode = document.createTextNode("");
|
||||||
editorRef.value.appendChild(textNode);
|
editorRef.value.appendChild(textNode);
|
||||||
@@ -408,6 +551,7 @@ const editApp = createApp({
|
|||||||
|
|
||||||
// 处理选中文本变化的函数
|
// 处理选中文本变化的函数
|
||||||
const handleSelectionChange = () => {
|
const handleSelectionChange = () => {
|
||||||
|
return;
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
// 确保有选中内容且选中区域在编辑器内
|
// 确保有选中内容且选中区域在编辑器内
|
||||||
if (selection.rangeCount > 0) {
|
if (selection.rangeCount > 0) {
|
||||||
@@ -560,7 +704,7 @@ const editApp = createApp({
|
|||||||
html = html.replace(/<(?!(a\b|\/a\b))[^>]+>/gi, "");
|
html = html.replace(/<(?!(a\b|\/a\b))[^>]+>/gi, "");
|
||||||
|
|
||||||
// 8. 清理连续换行(最多保留两个空行,避免过多空行)
|
// 8. 清理连续换行(最多保留两个空行,避免过多空行)
|
||||||
html = html.replace(/\n{3,}/g, "\n\n");
|
// html = html.replace(/\n{3,}/g, "\n\n");
|
||||||
// 去除首尾空白
|
// 去除首尾空白
|
||||||
html = html.trim();
|
html = html.trim();
|
||||||
|
|
||||||
@@ -745,7 +889,15 @@ const editApp = createApp({
|
|||||||
|
|
||||||
const linkClick = () => {};
|
const linkClick = () => {};
|
||||||
|
|
||||||
return { linkClick, insertVideo, insertLink, linkUrl, linkText, linkState, openLink, closeLink, handleClick, uniqid, userInfoWin, titleLength, submit, emojiState, openEmoji, closeEmoji, selectEmoji, optionEmoji, isPTitle, onEditorInput, onEditorFocus, onEditorBlur, paragraphTitle, info, tagList, token, cutAnonymity, editorRef, insertImage, judgeIsEmpty, isEmpty };
|
const overstriking = () => {
|
||||||
|
console.log("加粗");
|
||||||
|
|
||||||
|
editor.addMark("bold", true); // 加粗
|
||||||
|
editor.addMark("color", "#999"); // 文本颜色
|
||||||
|
console.log("editor", editor.addMark);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { overstriking, linkClick, insertVideo, insertLink, linkUrl, linkText, linkState, openLink, closeLink, handleClick, uniqid, userInfoWin, titleLength, submit, emojiState, openEmoji, closeEmoji, selectEmoji, optionEmoji, isPTitle, onEditorInput, onEditorFocus, onEditorBlur, paragraphTitle, info, tagList, token, cutAnonymity, editorRef, insertImage, judgeIsEmpty, isEmpty };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
24129
js/editor.js
Normal file
24129
js/editor.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user