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;
|
||||
position: relative;
|
||||
display: none;
|
||||
max-width: calc(100vw - 10px);
|
||||
}
|
||||
|
||||
.coins-area .coins-box .fork {
|
||||
|
||||
128
css/details.css
128
css/details.css
@@ -1,6 +1,7 @@
|
||||
#details {
|
||||
width: 1200px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
min-width: 320px;
|
||||
}
|
||||
#details .matter {
|
||||
align-items: flex-start;
|
||||
@@ -338,6 +339,7 @@
|
||||
}
|
||||
#details .matter .matter-left .related .list .item .text {
|
||||
width: 352px;
|
||||
flex: 1;
|
||||
}
|
||||
#details .matter .sidebar-box {
|
||||
position: sticky;
|
||||
@@ -845,30 +847,29 @@
|
||||
border-top: 1px dotted #ebebeb;
|
||||
}
|
||||
.answer-discuss .comments-box .comments-item .comments-header {
|
||||
justify-content: space-between;
|
||||
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;
|
||||
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;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
border-radius: 50%;
|
||||
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;
|
||||
margin-right: 10px;
|
||||
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;
|
||||
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;
|
||||
color: #7f7f7f;
|
||||
padding: 0 3px;
|
||||
@@ -877,18 +878,19 @@
|
||||
border: 1px solid #d7d7d7;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
.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;
|
||||
height: 14px;
|
||||
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;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
@@ -903,13 +905,13 @@
|
||||
background-color: #f6f6f6;
|
||||
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;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.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: "";
|
||||
width: 58px;
|
||||
height: 36px;
|
||||
@@ -918,7 +920,7 @@
|
||||
right: 0;
|
||||
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;
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
@@ -932,7 +934,7 @@
|
||||
color: #7f7f7f;
|
||||
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: "";
|
||||
width: 58px;
|
||||
height: 36px;
|
||||
@@ -940,23 +942,23 @@
|
||||
top: -14px;
|
||||
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;
|
||||
height: 13px;
|
||||
margin-left: 40px;
|
||||
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;
|
||||
color: #aaa;
|
||||
margin-left: 40px;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
.answer-discuss .comments-box .comments-item .comments-content {
|
||||
@@ -1251,3 +1253,89 @@
|
||||
z-index: 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
186
css/details.less
186
css/details.less
@@ -1,6 +1,8 @@
|
||||
#details {
|
||||
width: 1200px;
|
||||
// width: 1200px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
min-width: 320px;
|
||||
|
||||
.matter {
|
||||
align-items: flex-start;
|
||||
@@ -393,6 +395,7 @@
|
||||
|
||||
.text {
|
||||
width: 352px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -994,16 +997,16 @@
|
||||
}
|
||||
|
||||
.answer-discuss .comments-box .comments-item .comments-header {
|
||||
justify-content: space-between;
|
||||
// justify-content: space-between;
|
||||
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;
|
||||
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;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
@@ -1011,18 +1014,18 @@
|
||||
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;
|
||||
margin-right: 10px;
|
||||
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;
|
||||
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;
|
||||
color: #7f7f7f;
|
||||
padding: 0 3px;
|
||||
@@ -1032,21 +1035,22 @@
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
.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;
|
||||
height: 14px;
|
||||
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;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
@@ -1062,15 +1066,15 @@
|
||||
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;
|
||||
}
|
||||
|
||||
.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);
|
||||
}
|
||||
|
||||
.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: "";
|
||||
width: 58px;
|
||||
height: 36px;
|
||||
@@ -1080,7 +1084,7 @@
|
||||
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;
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
@@ -1095,7 +1099,7 @@
|
||||
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: "";
|
||||
width: 58px;
|
||||
height: 36px;
|
||||
@@ -1104,26 +1108,26 @@
|
||||
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;
|
||||
height: 13px;
|
||||
margin-left: 40px;
|
||||
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;
|
||||
color: #aaa;
|
||||
margin-left: 40px;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1458,3 +1462,145 @@
|
||||
z-index: 1;
|
||||
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
11
details.html
11
details.html
@@ -18,7 +18,7 @@
|
||||
<body>
|
||||
<sign-in-box></sign-in-box>
|
||||
<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">
|
||||
<img class="logo" src="https://oss.gter.net/logo" alt="" />
|
||||
@@ -211,7 +211,6 @@
|
||||
<div class="comments-box" v-if="commentTotalCount != 0">
|
||||
<div class="comments-item" v-for="(item, index) in commentList" :key="index">
|
||||
<div class="comments-header flexacenter">
|
||||
<div class="comments-header-left flexacenter">
|
||||
<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-time">{{ item["timestamp"] }}</div>
|
||||
@@ -229,8 +228,7 @@
|
||||
</a>
|
||||
<div class="avatar-mask" @click="closeUserInfo(index)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comments-header-right flexacenter">
|
||||
|
||||
<div class="menu-box flexacenter">
|
||||
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
||||
<!-- <div class="report-box flexcenter">举报</div> -->
|
||||
@@ -247,7 +245,6 @@
|
||||
<div class="like-quantity">{{ item["likenum"] || "" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comments-content">
|
||||
<div class="comments-text" v-if="item['content']" v-html="item['content']"></div>
|
||||
<div class="comments-img-box">
|
||||
@@ -285,7 +282,6 @@
|
||||
<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-header flexacenter">
|
||||
<div class="comments-header-left flexacenter">
|
||||
<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-time">{{ ite["timestamp"] }}</div>
|
||||
@@ -302,8 +298,6 @@
|
||||
</a>
|
||||
<div class="avatar-mask" @click="closeUserInfo(index, i)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comments-header-right flexacenter">
|
||||
<div class="menu-box flexacenter">
|
||||
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
||||
<div class="operate-box">
|
||||
@@ -319,7 +313,6 @@
|
||||
<div class="like-quantity">{{ ite["likenum"] || "" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comments-content">
|
||||
<div class="comments-text" v-if="ite['content']">
|
||||
<div class="comments-reply" v-if="ite?.reply?.nickname">@{{ ite["reply"]["nickname"] || "匿名用户" }}</div>
|
||||
|
||||
56
edit.html
56
edit.html
@@ -7,21 +7,40 @@
|
||||
<title>发布帖子 - 轻论坛</title>
|
||||
<link rel="stylesheet" href="./css/public.css" />
|
||||
<link rel="stylesheet" href="./css/edit.css" />
|
||||
<link href="./css/editor.css" rel="stylesheet" />
|
||||
|
||||
<script src="./js/vue.global.js"></script>
|
||||
<style>
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
</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>
|
||||
|
||||
<body>
|
||||
<div class="container" id="edit" v-cloak>
|
||||
<div class="edit-head flexacenter">
|
||||
<div class="edit-head-container flexacenter">
|
||||
<a class="" href="/" target="_blank">
|
||||
<img class="icon" src="{@/img/edit-logo-icon.png}" />
|
||||
</a>
|
||||
<a class="" href="/" target="_blank"><img class="icon" src="{@/img/edit-logo-icon.png}" /></a>
|
||||
<div class="dot"></div>
|
||||
<div class="title">发帖</div>
|
||||
<div class="hint">发帖奖励 3 个寄托币/篇,每天最高奖励3篇</div>
|
||||
@@ -32,13 +51,13 @@
|
||||
<div class="edit-container">
|
||||
<!-- 标题输入 -->
|
||||
<div class="title-box">
|
||||
<input class="title-input" type="title" placeholder="输入标题(非必填)" v-model="info.title"
|
||||
:maxlength="titleLength" />
|
||||
<input class="title-input" type="title" placeholder="输入标题(非必填)" v-model="info.title" :maxlength="titleLength" />
|
||||
<div class="sum">{{ info?.title?.length ? titleLength - info?.title?.length : titleLength }}</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">
|
||||
<img class="icon" src="{@/img/t-icon.png}" alt="段落标题" />
|
||||
<span>段落标题</span>
|
||||
@@ -58,8 +77,7 @@
|
||||
<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 class="emoji-icon" v-for="emoji in optionEmoji" :key="emoji" @click.stop="selectEmoji(emoji)">{{ emoji }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar-item flexacenter link" :class="{'pitch': linkState}" @click="openLink">
|
||||
@@ -78,17 +96,23 @@
|
||||
<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 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>
|
||||
|
||||
<!-- 标签选择 -->
|
||||
<!-- <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 id="toolbar-container"></div> -->
|
||||
<div id="editor-container"><!-- 编辑器 --></div>
|
||||
</div>
|
||||
<!-- 内容编辑区 -->
|
||||
<!-- <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> -->
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<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() {
|
||||
onMounted(() => {
|
||||
getUserInfoWin();
|
||||
setTimeout(() => {
|
||||
SignInComponent.initComponent();
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
let isLogin = ref(false);
|
||||
|
||||
170
js/edit.js
170
js/edit.js
@@ -1,6 +1,8 @@
|
||||
// 简单版本的论坛编辑器,确保图片插入功能正常
|
||||
const { createApp, ref, computed, onMounted, nextTick, onUnmounted } = Vue;
|
||||
import { headTop } from "../component/head-top/head-top.js";
|
||||
const { createEditor, createToolbar } = window.wangEditor;
|
||||
console.log("createEditor", createEditor);
|
||||
|
||||
const editApp = createApp({
|
||||
setup() {
|
||||
@@ -12,11 +14,9 @@ const editApp = createApp({
|
||||
uniqid.value = params.uniqid || "";
|
||||
|
||||
getUserInfoWin();
|
||||
checkWConfig();
|
||||
|
||||
cUpload();
|
||||
init();
|
||||
|
||||
checkWConfig();
|
||||
|
||||
// 添加selectionchange事件监听,当鼠标选中区域内容时更新lastSelection
|
||||
document.addEventListener("selectionchange", handleSelectionChange);
|
||||
@@ -107,6 +107,10 @@ const editApp = createApp({
|
||||
ajaxGet(`/v2/api/config/upload?type=topic`).then((res) => {
|
||||
const data = res.data;
|
||||
uConfigData = data;
|
||||
|
||||
console.log("uConfigData", uConfigData);
|
||||
|
||||
init();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -132,15 +136,153 @@ const editApp = createApp({
|
||||
info.value = infoTarget;
|
||||
token.value = data.token;
|
||||
|
||||
nextTick(() => {
|
||||
judgeIsEmpty();
|
||||
});
|
||||
// nextTick(() => {
|
||||
// judgeIsEmpty();
|
||||
// });
|
||||
|
||||
initEditor();
|
||||
})
|
||||
.catch((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 imageList = attachments?.images || [];
|
||||
|
||||
@@ -196,7 +338,7 @@ const editApp = createApp({
|
||||
html = html.replace(/(<span class="blue">[^<]+<\/span>)\s+/gi, '$1 <span class="fill"></span> ');
|
||||
|
||||
// 7. 清理多余的<br>标签
|
||||
html = html.replace(/<br><br>/g, "<br>");
|
||||
// html = html.replace(/<br><br>/g, "<br>");
|
||||
|
||||
imageList.forEach((element) => {
|
||||
html += `<img src="${element.url}" data-aid="${element.aid}"><br/>`;
|
||||
@@ -218,6 +360,7 @@ const editApp = createApp({
|
||||
const editorRef = ref(null);
|
||||
|
||||
const focusLastNode = () => {
|
||||
return;
|
||||
const newRange = document.createRange();
|
||||
const textNode = document.createTextNode("");
|
||||
editorRef.value.appendChild(textNode);
|
||||
@@ -408,6 +551,7 @@ const editApp = createApp({
|
||||
|
||||
// 处理选中文本变化的函数
|
||||
const handleSelectionChange = () => {
|
||||
return;
|
||||
const selection = window.getSelection();
|
||||
// 确保有选中内容且选中区域在编辑器内
|
||||
if (selection.rangeCount > 0) {
|
||||
@@ -560,7 +704,7 @@ const editApp = createApp({
|
||||
html = html.replace(/<(?!(a\b|\/a\b))[^>]+>/gi, "");
|
||||
|
||||
// 8. 清理连续换行(最多保留两个空行,避免过多空行)
|
||||
html = html.replace(/\n{3,}/g, "\n\n");
|
||||
// html = html.replace(/\n{3,}/g, "\n\n");
|
||||
// 去除首尾空白
|
||||
html = html.trim();
|
||||
|
||||
@@ -745,7 +889,15 @@ const editApp = createApp({
|
||||
|
||||
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