refactor(editor): 重构编辑器组件及样式,优化功能实现
重构编辑器工具栏样式及功能,使用wangEditor替换原有实现 优化图片和视频上传逻辑,增加自定义校验和上传处理 调整编辑器样式,修复对齐功能及段落标题样式 更新表情选择器位置逻辑,支持上下方向显示 统一组件导入方式,添加版本控制参数防止缓存
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref, inject } = Vue;
|
const { defineComponent, ref, inject } = Vue;
|
||||||
import { like } from "../like/like.js";
|
|
||||||
|
const { like } = await import(withVer("../like/like.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemBottom = defineComponent({
|
export const itemBottom = defineComponent({
|
||||||
name: "item-bottom",
|
name: "item-bottom",
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref } = Vue;
|
const { defineComponent, ref } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemForum = defineComponent({
|
export const itemForum = defineComponent({
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref, provide, onMounted, inject } = Vue;
|
const { defineComponent, ref, provide, onMounted, inject } = Vue;
|
||||||
import { report } from "../report/report.js";
|
|
||||||
|
const { report } = await import(withVer("../report/report.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemHead = defineComponent({
|
export const itemHead = defineComponent({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref } = Vue;
|
const { defineComponent, ref } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemMj = defineComponent({
|
export const itemMj = defineComponent({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref, provide } = Vue;
|
const { defineComponent, ref, provide } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemOffer = defineComponent({
|
export const itemOffer = defineComponent({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref } = Vue;
|
const { defineComponent, ref } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemSummary = defineComponent({
|
export const itemSummary = defineComponent({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref } = Vue;
|
const { defineComponent, ref } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemTenement = defineComponent({
|
export const itemTenement = defineComponent({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref } = Vue;
|
const { defineComponent, ref } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const itemVote = defineComponent({
|
export const itemVote = defineComponent({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// my-component.js
|
// my-component.js
|
||||||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||||||
const { defineComponent, ref, onMounted, nextTick } = Vue;
|
const { defineComponent, ref, onMounted, nextTick } = Vue;
|
||||||
import { itemBottom } from "../item-bottom/item-bottom.js";
|
|
||||||
import { itemHead } from "../item-head/item-head.js";
|
const { itemBottom } = await import(withVer("../item-bottom/item-bottom.js"));
|
||||||
|
const { itemHead } = await import(withVer("../item-head/item-head.js"));
|
||||||
|
|
||||||
// 定义组件(直接使用模板)
|
// 定义组件(直接使用模板)
|
||||||
export const latestList = defineComponent({
|
export const latestList = defineComponent({
|
||||||
|
|||||||
@@ -77,7 +77,14 @@ export const slideshowBox = defineComponent({
|
|||||||
tabPitch.value = key;
|
tabPitch.value = key;
|
||||||
};
|
};
|
||||||
|
|
||||||
return { tabItem, tabPitch, tabPitch, latestList };
|
const handleCheckAttest = (e) => {
|
||||||
|
if (realname.value === 0 && userInfoWin.value?.uin > 0) {
|
||||||
|
openAttest();
|
||||||
|
e.preventDefault(); // 阻止默认跳转(即使 href 为链接,也强制拦截)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleCheckAttest, tabItem, tabPitch, tabPitch, latestList };
|
||||||
},
|
},
|
||||||
|
|
||||||
template: `<div class="box-box" :class="['box-' + tabPitch]"> <div class="slideshow-box"> <div class="tab-list flexacenter"> <!-- <div class="tab-item thread" :class="{'pitch': tabPitch == 'thread'}" @click="tabItem('thread')">帖子</div> --> <div class="tab-item offer" :class="{'pitch': tabPitch == 'offer'}" @click="tabItem('offer')">Offer</div> <div class="tab-item vote" :class="{'pitch': tabPitch == 'vote'}" @click="tabItem('vote')">投票</div> <div class="tab-item interviewexperience" :class="{'pitch': tabPitch == 'interviewexperience'}" @click="tabItem('interviewexperience')">面经</div> </div> </div> <div class="slideshow-content flexflex"> <!-- 问答 --> <!-- <div class="thread-side-box side-box"> <div class="box"> <a v-for="item in latestList.thread" :key="item.uniqid" class="item" target="_blank" :href="'/details/' + item.uniqid"> <div class="question flexacenter"> <div class="text flex1 ellipsis">{{ item.title }}</div> </div> <div class="answer flexacenter"> <div class="text flex1"> <div class="texttext">{{ item.content }}</div> </div> </div> </a> <a class="add-btn flexcenter" href="https://ask.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> --> <!-- offer --> <div class="offer-side-box side-box"> <div class="box"> <a v-for="item in latestList.offer" :key="item.uniqid" class="item flexflex" :href="'/details/' + item.uniqid" target="_blank"> <img class="school-img" :src="item.data.schoollogo" /> <div class="school-detail flex1 flexflex"> <div class="school-name one-line-display">{{ item.data.schoolname }}</div> <div class="school-brief one-line-display">{{ item.data.professional }}</div> <div class="school-offer flexacenter"> <span>{{ item.data.degree }}</span> <span class="long-string">|</span> <span>{{ item.data.semester }}</span> <span class="long-string">|</span> <span>{{ item.data.apply_results_text }}</span> </div> </div> </a> <a class="add-btn flexcenter" href="https://offer.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> <!-- 投票 --> <div class="vote-side-box side-box"> <div class="box"> <a v-for="item in latestList.vote" :key="item.uniqid" class="item flexflex vuehide" target="_blank" :href="'/details/' + item.uniqid"> <div class="name one-line-display">{{ item.title }}</div> <div class="brief">{{ item.content }}</div> </a> <a class="add-btn flexcenter" href="https://vote.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> <!-- mj --> <div class="interviewexperience-side-box side-box"> <div class="box"> <a v-for="item in latestList.interviewexperience" :key="item.thread_id" class="item flexflex" :href="'/details/' + item.uniqid" target="_blank"> <div class="school one-line-display">{{ item.data.schoolname }}</div> <div class="major one-line-display">{{ item.data.project }}</div> <div class="info"> <img class="icon" :src="item.user.avatar" /> <span class="text">{{ item.title || item.content }} </span> </div> </a> <a class="add-btn flexcenter" href="https://interviewexperience.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> </div></div>`,
|
template: `<div class="box-box" :class="['box-' + tabPitch]"> <div class="slideshow-box"> <div class="tab-list flexacenter"> <!-- <div class="tab-item thread" :class="{'pitch': tabPitch == 'thread'}" @click="tabItem('thread')">帖子</div> --> <div class="tab-item offer" :class="{'pitch': tabPitch == 'offer'}" @click="tabItem('offer')">Offer</div> <div class="tab-item vote" :class="{'pitch': tabPitch == 'vote'}" @click="tabItem('vote')">投票</div> <div class="tab-item interviewexperience" :class="{'pitch': tabPitch == 'interviewexperience'}" @click="tabItem('interviewexperience')">面经</div> </div> </div> <div class="slideshow-content flexflex"> <!-- 问答 --> <!-- <div class="thread-side-box side-box"> <div class="box"> <a v-for="item in latestList.thread" :key="item.uniqid" class="item" target="_blank" :href="'/details/' + item.uniqid"> <div class="question flexacenter"> <div class="text flex1 ellipsis">{{ item.title }}</div> </div> <div class="answer flexacenter"> <div class="text flex1"> <div class="texttext">{{ item.content }}</div> </div> </div> </a> <a class="add-btn flexcenter" href="https://ask.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> --> <!-- offer --> <div class="offer-side-box side-box"> <div class="box"> <a v-for="item in latestList.offer" :key="item.uniqid" class="item flexflex" :href="'/details/' + item.uniqid" target="_blank"> <img class="school-img" :src="item.data.schoollogo" /> <div class="school-detail flex1 flexflex"> <div class="school-name one-line-display">{{ item.data.schoolname }}</div> <div class="school-brief one-line-display">{{ item.data.professional }}</div> <div class="school-offer flexacenter"> <span>{{ item.data.degree }}</span> <span class="long-string">|</span> <span>{{ item.data.semester }}</span> <span class="long-string">|</span> <span>{{ item.data.apply_results_text }}</span> </div> </div> </a> <a class="add-btn flexcenter" href="https://offer.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> <!-- 投票 --> <div class="vote-side-box side-box"> <div class="box"> <a v-for="item in latestList.vote" :key="item.uniqid" class="item flexflex vuehide" target="_blank" :href="'/details/' + item.uniqid"> <div class="name one-line-display">{{ item.title }}</div> <div class="brief">{{ item.content }}</div> </a> <a class="add-btn flexcenter" href="https://vote.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> <!-- mj --> <div class="interviewexperience-side-box side-box"> <div class="box"> <a v-for="item in latestList.interviewexperience" :key="item.thread_id" class="item flexflex" :href="'/details/' + item.uniqid" target="_blank"> <div class="school one-line-display">{{ item.data.schoolname }}</div> <div class="major one-line-display">{{ item.data.project }}</div> <div class="info"> <img class="icon" :src="item.user.avatar" /> <span class="text">{{ item.title || item.content }} </span> </div> </a> <a class="add-btn flexcenter" href="https://interviewexperience.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> </div></div>`,
|
||||||
|
|||||||
@@ -761,6 +761,15 @@
|
|||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
.answer-discuss .input-box .bottom .operate .item .emoji-box.top {
|
||||||
|
top: inherit;
|
||||||
|
bottom: 36px;
|
||||||
|
}
|
||||||
|
.answer-discuss .input-box .bottom .operate .item .emoji-box.top::after {
|
||||||
|
bottom: -8px;
|
||||||
|
top: inherit;
|
||||||
|
transform: translateX(-50%) rotate(180deg);
|
||||||
|
}
|
||||||
.answer-discuss .input-box .bottom .operate .item .emoji-box::after {
|
.answer-discuss .input-box .bottom .operate .item .emoji-box::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|||||||
@@ -878,16 +878,17 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.answer-discuss .input-box .bottom .operate .item {
|
||||||
|
}
|
||||||
|
|
||||||
.answer-discuss .input-box .bottom .operate .item .emoji-box {
|
.answer-discuss .input-box .bottom .operate .item .emoji-box {
|
||||||
width: 582px;
|
width: 582px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
filter: drop-shadow(0 0 11px rgba(0, 0, 0, 0.1));
|
filter: drop-shadow(0 0 11px rgba(0, 0, 0, 0.1));
|
||||||
// top: 45px;
|
|
||||||
top: 36px;
|
top: 36px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
// left: -14px;
|
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
border: 1px solid #ebebeb;
|
border: 1px solid #ebebeb;
|
||||||
@@ -895,20 +896,30 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
|
||||||
|
|
||||||
.answer-discuss .input-box .bottom .operate .item .emoji-box::after {
|
&.top {
|
||||||
content: "";
|
top: inherit;
|
||||||
width: 0;
|
bottom: 36px;
|
||||||
height: 0;
|
|
||||||
border-left: 8px solid transparent;
|
&::after {
|
||||||
border-right: 8px solid transparent;
|
bottom: -8px;
|
||||||
border-bottom: 8px solid #ffffff;
|
top: inherit;
|
||||||
position: absolute;
|
transform: translateX(-50%) rotate(180deg);
|
||||||
top: -8px;
|
}
|
||||||
// left: 15px;
|
}
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
&::after {
|
||||||
|
content: "";
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 8px solid transparent;
|
||||||
|
border-right: 8px solid transparent;
|
||||||
|
border-bottom: 8px solid #ffffff;
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-discuss .input-box .bottom .operate .item .emoji-box .emoji-icon {
|
.answer-discuss .input-box .bottom .operate .item .emoji-box .emoji-icon {
|
||||||
|
|||||||
99
css/edit.css
99
css/edit.css
@@ -73,18 +73,44 @@
|
|||||||
color: #555;
|
color: #555;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar {
|
#edit .edit-container #editor—wrapper {
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
background-color: #fbfbfb;
|
background-color: #fbfbfb;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item {
|
#edit .edit-container #editor—wrapper .editor-toolbar .w-e-panel-content-emotion {
|
||||||
|
width: 490px;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .w-e-bar-item-group .w-e-bar-item-menus-container {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar > .w-e-bar {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .w-e-toolbar {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .w-e-toolbar > .w-e-bar-item {
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .w-e-toolbar > .w-e-bar-item > button {
|
||||||
|
color: #000000;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 30px;
|
height: 30px !important;
|
||||||
line-height: 30px;
|
line-height: 30px !important;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -93,15 +119,21 @@
|
|||||||
line-height: 23px;
|
line-height: 23px;
|
||||||
margin-right: 40px;
|
margin-right: 40px;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 10px;
|
padding: 0;
|
||||||
border-radius: 50px;
|
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .icon {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .file {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item > button {
|
||||||
|
padding: 0 10px;
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item > button.active {
|
||||||
|
background-color: #f6f6bd;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .file {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
/* 隐藏输入框 */
|
/* 隐藏输入框 */
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@@ -113,7 +145,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .file::after {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .file::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -121,14 +153,14 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.expression.pitch .emoji-box-mask {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.expression.pitch .emoji-box-mask {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.expression.pitch .emoji-box {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.expression.pitch .emoji-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .link-box-mask,
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .link-box-mask,
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .emoji-box-mask {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .emoji-box-mask {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -137,10 +169,10 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .link-box-mask {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .link-box-mask {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .emoji-box {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .emoji-box {
|
||||||
width: 582px;
|
width: 582px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
@@ -156,7 +188,7 @@
|
|||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .emoji-box::after {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .emoji-box::after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
@@ -168,17 +200,17 @@
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item .emoji-box .emoji-icon {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .emoji-box .emoji-icon {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link.pitch .link-box-mask {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link.pitch .link-box-mask {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link.pitch .link-box {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link.pitch .link-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link .link-box {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link .link-box {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.16862745);
|
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.16862745);
|
||||||
@@ -193,11 +225,11 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 18px 20px 0;
|
padding: 18px 20px 0;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link .link-box .item {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link .link-box .item {
|
||||||
margin-bottom: 22px;
|
margin-bottom: 22px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link .link-box .item .name {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link .link-box .item .name {
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -206,7 +238,7 @@
|
|||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link .link-box .item .input {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link .link-box .item .input {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
border: 1px solid #d7d7d7;
|
border: 1px solid #d7d7d7;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
@@ -214,7 +246,7 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link .link-box .btn {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link .link-box .btn {
|
||||||
width: 72px;
|
width: 72px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
@@ -228,12 +260,27 @@
|
|||||||
color: #000000;
|
color: #000000;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.link .link-box .btn:hover {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.link .link-box .btn:hover {
|
||||||
background-color: #23e0b6;
|
background-color: #23e0b6;
|
||||||
}
|
}
|
||||||
#edit .edit-container .editor-toolbar .toolbar-item.h2.pitch {
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.h2.pitch {
|
||||||
background-color: #f6f6bd;
|
background-color: #f6f6bd;
|
||||||
}
|
}
|
||||||
|
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item.active > button {
|
||||||
|
background-color: #f6f6bd;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper #editor-container {
|
||||||
|
min-height: 500px;
|
||||||
|
max-height: 80vh;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 26px;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
#edit .edit-container #editor—wrapper #editor-container a {
|
||||||
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #04b0d5;
|
||||||
|
}
|
||||||
#edit .edit-container .content-input {
|
#edit .edit-container .content-input {
|
||||||
min-height: 509px;
|
min-height: 509px;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
|
|||||||
367
css/edit.less
367
css/edit.less
@@ -82,192 +82,253 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar {
|
#editor—wrapper {
|
||||||
height: 36px;
|
z-index: 100;
|
||||||
background-color: rgba(251, 251, 251, 1);
|
|
||||||
padding-left: 25px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
.toolbar-item {
|
.bold {
|
||||||
.icon {
|
font-weight: bold;
|
||||||
width: 16px;
|
}
|
||||||
height: 16px;
|
|
||||||
margin-right: 5px;
|
.editor-toolbar {
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
background-color: rgba(251, 251, 251, 1);
|
||||||
|
padding-left: 25px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
.w-e-panel-content-emotion {
|
||||||
|
width: 490px;
|
||||||
|
}
|
||||||
|
.w-e-bar-item-group .w-e-bar-item-menus-container {
|
||||||
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor: pointer;
|
> .w-e-bar {
|
||||||
height: 30px;
|
background-color: transparent;
|
||||||
line-height: 30px;
|
}
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
.w-e-toolbar {
|
||||||
font-weight: 400;
|
padding: 0;
|
||||||
font-style: normal;
|
// .w-e-bar-item {
|
||||||
font-size: 14px;
|
// padding: 0 10px;
|
||||||
color: #000000;
|
// }
|
||||||
line-height: 23px;
|
|
||||||
margin-right: 40px;
|
> .w-e-bar-item {
|
||||||
position: relative;
|
margin-right: 40px;
|
||||||
padding: 0 10px;
|
> button {
|
||||||
border-radius: 50px;
|
color: #000000;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-item {
|
||||||
|
.icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.file {
|
|
||||||
opacity: 0; /* 隐藏输入框 */
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
height: 30px !important;
|
||||||
|
line-height: 30px !important;
|
||||||
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #000000;
|
||||||
|
line-height: 23px;
|
||||||
|
margin-right: 40px;
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
&::after {
|
> button {
|
||||||
content: "";
|
padding: 0 10px;
|
||||||
width: 100%;
|
border-radius: 50px;
|
||||||
height: 100%;
|
|
||||||
|
&.active {
|
||||||
|
background-color: rgba(246, 246, 189, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file {
|
||||||
|
opacity: 0; /* 隐藏输入框 */
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
width: 100%;
|
||||||
}
|
height: 100%;
|
||||||
|
|
||||||
&.expression.pitch {
|
|
||||||
.emoji-box-mask {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji-box {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-box-mask,
|
|
||||||
.emoji-box-mask {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
z-index: 1;
|
|
||||||
// background-color: rgba(0, 0, 0, 0.20392157);
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-box-mask {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji-box {
|
|
||||||
width: 582px;
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: #fff;
|
|
||||||
filter: drop-shadow(0 0 11px rgba(0, 0, 0, 0.1));
|
|
||||||
top: 45px;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
border: 1px solid #ebebeb;
|
|
||||||
display: none;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
font-size: 22px;
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: "";
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
border-left: 8px solid transparent;
|
|
||||||
border-right: 8px solid transparent;
|
|
||||||
border-bottom: 8px solid #ffffff;
|
|
||||||
position: absolute;
|
|
||||||
top: -8px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji-icon {
|
|
||||||
margin: 5px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.link {
|
&::after {
|
||||||
&.pitch {
|
content: "";
|
||||||
.link-box-mask {
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.expression.pitch {
|
||||||
|
.emoji-box-mask {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-box {
|
.emoji-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-box {
|
.link-box-mask,
|
||||||
background-color: rgba(255, 255, 255, 1);
|
.emoji-box-mask {
|
||||||
border-radius: 6px;
|
position: fixed;
|
||||||
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.168627450980392);
|
top: 0;
|
||||||
|
left: 0;
|
||||||
width: 336px;
|
width: 100%;
|
||||||
height: 282px;
|
height: 100%;
|
||||||
position: absolute;
|
|
||||||
top: 30px;
|
|
||||||
left: 0%;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
// background-color: rgba(0, 0, 0, 0.20392157);
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-box-mask {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-box {
|
||||||
|
width: 582px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #fff;
|
||||||
|
filter: drop-shadow(0 0 11px rgba(0, 0, 0, 0.1));
|
||||||
|
top: 45px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
border: 1px solid #ebebeb;
|
border: 1px solid #ebebeb;
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-wrap: wrap;
|
||||||
padding: 18px 20px 0;
|
font-size: 22px;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
.item {
|
&::after {
|
||||||
margin-bottom: 22px;
|
content: "";
|
||||||
flex-direction: column;
|
width: 0;
|
||||||
.name {
|
height: 0;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
border-left: 8px solid transparent;
|
||||||
font-weight: 400;
|
border-right: 8px solid transparent;
|
||||||
font-style: normal;
|
border-bottom: 8px solid #ffffff;
|
||||||
font-size: 14px;
|
position: absolute;
|
||||||
color: #555555;
|
top: -8px;
|
||||||
line-height: 26px;
|
left: 50%;
|
||||||
margin-bottom: 8px;
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-icon {
|
||||||
|
margin: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.link {
|
||||||
|
&.pitch {
|
||||||
|
.link-box-mask {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.link-box {
|
||||||
height: 36px;
|
display: flex;
|
||||||
border: 1px solid rgba(215, 215, 215, 1);
|
|
||||||
border-radius: 7px;
|
|
||||||
padding: 0 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #000000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.link-box {
|
||||||
width: 72px;
|
background-color: rgba(255, 255, 255, 1);
|
||||||
height: 40px;
|
border-radius: 6px;
|
||||||
line-height: 40px;
|
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.168627450980392);
|
||||||
background-color: rgba(80, 227, 194, 1);
|
|
||||||
border-radius: 8px;
|
width: 336px;
|
||||||
margin-left: auto;
|
height: 282px;
|
||||||
font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif;
|
position: absolute;
|
||||||
font-weight: 650;
|
top: 30px;
|
||||||
font-style: normal;
|
left: 0%;
|
||||||
font-size: 16px;
|
z-index: 1;
|
||||||
color: #000000;
|
|
||||||
margin-top: 8px;
|
border: 1px solid #ebebeb;
|
||||||
&:hover {
|
display: none;
|
||||||
background-color: rgb(35, 224, 182);
|
flex-direction: column;
|
||||||
|
padding: 18px 20px 0;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin-bottom: 22px;
|
||||||
|
flex-direction: column;
|
||||||
|
.name {
|
||||||
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555555;
|
||||||
|
line-height: 26px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
height: 36px;
|
||||||
|
border: 1px solid rgba(215, 215, 215, 1);
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 72px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
background-color: rgba(80, 227, 194, 1);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-left: auto;
|
||||||
|
font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif;
|
||||||
|
font-weight: 650;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #000000;
|
||||||
|
margin-top: 8px;
|
||||||
|
&:hover {
|
||||||
|
background-color: rgb(35, 224, 182);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.h2 {
|
||||||
|
&.pitch {
|
||||||
|
background-color: rgba(246, 246, 189, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
> button {
|
||||||
|
background-color: rgba(246, 246, 189, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.h2 {
|
#editor-container {
|
||||||
&.pitch {
|
min-height: 500px;
|
||||||
background-color: rgba(246, 246, 189, 1);
|
max-height: 80vh;
|
||||||
}
|
font-size: 18px;
|
||||||
|
line-height: 26px;
|
||||||
|
color: #333333;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #04b0d5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,15 +109,18 @@
|
|||||||
height: 26px;
|
height: 26px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(6) {
|
|
||||||
margin-right: -9px;
|
|
||||||
}
|
|
||||||
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(5) {
|
|
||||||
margin-right: -9px;
|
|
||||||
}
|
|
||||||
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(4) {
|
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(4) {
|
||||||
|
margin-right: -9px;
|
||||||
|
}
|
||||||
|
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(3) {
|
||||||
|
margin-right: -9px;
|
||||||
|
}
|
||||||
|
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(2) {
|
||||||
margin-right: -7px;
|
margin-right: -7px;
|
||||||
}
|
}
|
||||||
|
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-head .people .right .item:nth-child(2) {
|
||||||
|
margin-right: -5px;
|
||||||
|
}
|
||||||
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-list .item {
|
#appIndex .header-content-box .header-content-left .topic-and-selectives .topic-box .topic-list .item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,17 +125,18 @@
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(6) {
|
|
||||||
margin-right: -9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(5) {
|
|
||||||
margin-right: -9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(4) {
|
&:nth-child(4) {
|
||||||
|
margin-right: -9px;
|
||||||
|
}
|
||||||
|
&:nth-child(3) {
|
||||||
|
margin-right: -9px;
|
||||||
|
}
|
||||||
|
&:nth-child(2) {
|
||||||
margin-right: -7px;
|
margin-right: -7px;
|
||||||
}
|
}
|
||||||
|
&:nth-child(2) {
|
||||||
|
margin-right: -5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
font-weight: 400;
|
// font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@
|
|||||||
<div class="bottom flexacenter">
|
<div class="bottom flexacenter">
|
||||||
<div class="operate flexacenter">
|
<div class="operate flexacenter">
|
||||||
<div class="item" :class="{ 'pitch': emojiState }" style="z-index: 2">
|
<div class="item" :class="{ 'pitch': emojiState }" style="z-index: 2">
|
||||||
<img class="icon" src="./img/smiling-face.png" @click="openEmoji()" alt="" />
|
<img class="icon" src="./img/smiling-face.png" @click="openEmoji($event)" alt="" />
|
||||||
<div class="emoji-box">
|
<div class="emoji-box">
|
||||||
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item)">{{ item }}</div>
|
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item)">{{ item }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -264,7 +264,7 @@
|
|||||||
<div class="bottom flexacenter">
|
<div class="bottom flexacenter">
|
||||||
<div class="operate flexacenter">
|
<div class="operate flexacenter">
|
||||||
<div class="item" :class="{ 'pitch': item.emojiState }" style="z-index: 2">
|
<div class="item" :class="{ 'pitch': item.emojiState }" style="z-index: 2">
|
||||||
<img class="icon" src="./img/smiling-face.png" @click="openEmoji(index)" alt="" />
|
<img class="icon" src="./img/smiling-face.png" @click="openEmoji($event, index)" alt="" />
|
||||||
<div class="emoji-box">
|
<div class="emoji-box">
|
||||||
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item, index)">{{ item }}</div>
|
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item, index)">{{ item }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
<div class="bottom flexacenter">
|
<div class="bottom flexacenter">
|
||||||
<div class="operate flexacenter">
|
<div class="operate flexacenter">
|
||||||
<div class="item" :class="{ 'pitch': ite.emojiState }" style="z-index: 2">
|
<div class="item" :class="{ 'pitch': ite.emojiState }" style="z-index: 2">
|
||||||
<img class="icon" src="./img/smiling-face.png" @click="openEmoji(index, i)" alt="" />
|
<img class="icon" src="./img/smiling-face.png" @click="openEmoji($event, index, i)" alt="" />
|
||||||
<div class="emoji-box">
|
<div class="emoji-box">
|
||||||
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item, index, i)">{{ item }}</div>
|
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item, index, i)">{{ item }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -481,7 +481,7 @@
|
|||||||
<script src="./js/axios.min.js"></script>
|
<script src="./js/axios.min.js"></script>
|
||||||
<script src="./js/public.js"></script>
|
<script src="./js/public.js"></script>
|
||||||
<script type="module" src="./js/details.js"></script>
|
<script type="module" src="./js/details.js"></script>
|
||||||
<script type="module" src=" https://app.gter.net/image/gter/commonCom/preview-image/preview.js"></script>
|
<script type="module" src=" https://app.gter.net/image/gter/commonCom/preview-image/preview.js?v=${window.__ASSET_VERSION__}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
26
edit.html
26
edit.html
@@ -16,24 +16,7 @@
|
|||||||
}
|
}
|
||||||
</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>
|
<script src="./js/editor.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -54,11 +37,12 @@
|
|||||||
<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 class="sum">{{ info?.title?.length ? titleLength - info?.title?.length : titleLength }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="editor—wrapper">
|
|
||||||
|
<div id="editor—wrapper" class="editor—wrapper">
|
||||||
|
|
||||||
<!-- 工具栏 -->
|
<!-- 工具栏 -->
|
||||||
<div id="toolbar-container" class="editor-toolbar flexacenter">
|
<div ref="toolbarRef" 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>
|
||||||
@@ -104,7 +88,7 @@
|
|||||||
<div class="emoji-box">
|
<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>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch, provide } = Vue;
|
const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch, provide } = Vue;
|
||||||
import { itemForum } from "../component/item-forum/item-forum.js";
|
const ASSET_VERSION = window.__ASSET_VERSION__ || "20251126";
|
||||||
import { itemOffer } from "../component/item-offer/item-offer.js";
|
const withVer = (p) => `${p}?v=${ASSET_VERSION}`;
|
||||||
import { itemSummary } from "../component/item-summary/item-summary.js";
|
const { itemForum } = await import(withVer("../component/item-forum/item-forum.js"));
|
||||||
import { itemVote } from "../component/item-vote/item-vote.js";
|
const { itemOffer } = await import(withVer("../component/item-offer/item-offer.js"));
|
||||||
import { itemMj } from "../component/item-mj/item-mj.js";
|
const { itemSummary } = await import(withVer("../component/item-summary/item-summary.js"));
|
||||||
import { itemTenement } from "../component/item-tenement/item-tenement.js";
|
const { itemVote } = await import(withVer("../component/item-vote/item-vote.js"));
|
||||||
import { latestList } from "../component/latest-list/latest-list.js";
|
const { itemMj } = await import(withVer("../component/item-mj/item-mj.js"));
|
||||||
import { slideshowBox } from "../component/slideshow-box/slideshow-box.js";
|
const { itemTenement } = await import(withVer("../component/item-tenement/item-tenement.js"));
|
||||||
import { like } from "../component/like/like.js";
|
const { latestList } = await import(withVer("../component/latest-list/latest-list.js"));
|
||||||
import { report } from "../component/report/report.js";
|
const { slideshowBox } = await import(withVer("../component/slideshow-box/slideshow-box.js"));
|
||||||
import { headTop } from "../component/head-top/head-top.js";
|
const { like } = await import(withVer("../component/like/like.js"));
|
||||||
|
const { report } = await import(withVer("../component/report/report.js"));
|
||||||
|
const { headTop } = await import(withVer("../component/head-top/head-top.js"));
|
||||||
|
|
||||||
const appSectionIndex = createApp({
|
const appSectionIndex = createApp({
|
||||||
setup() {
|
setup() {
|
||||||
@@ -563,10 +565,11 @@ const appSectionIndex = createApp({
|
|||||||
|
|
||||||
let emojiState = ref(false);
|
let emojiState = ref(false);
|
||||||
let emojiMaskState = ref(false);
|
let emojiMaskState = ref(false);
|
||||||
|
let emojiBottomDistance = ref(0);
|
||||||
let inputTextarea = ref("");
|
let inputTextarea = ref("");
|
||||||
|
|
||||||
// 打开 Emoji
|
// 打开 Emoji
|
||||||
const openEmoji = (index, i) => {
|
const openEmoji = (event, index, i) => {
|
||||||
if (!isLogin.value) {
|
if (!isLogin.value) {
|
||||||
goLogin();
|
goLogin();
|
||||||
return;
|
return;
|
||||||
@@ -1177,7 +1180,7 @@ const appSectionIndex = createApp({
|
|||||||
ajax(`/v2/api/forum/postTopicShare`, { token });
|
ajax(`/v2/api/forum/postTopicShare`, { token });
|
||||||
};
|
};
|
||||||
|
|
||||||
return { uniqidRef, share, reportToken, isReplyBoxShow, matterHeight, sidebarHeight, deleteItem, maxPicture, sidebarFixed, matterRef, sidebarRef, pitchInputState, ismyself, edit, searchInput, defaultSearchText, goSearch, goPersonalHomepage, QRcode, alsoCommentsData, copyLinkClick, reportState, tokentoken, essence, recommend, hide, report, cutShow, ismanager, show, openDiscuss, commentDelete, handleInputPaste, autoResize, editCommentState, selectEditEmoji, closeEditEmoji, openEditEmoji, closeEdit, openEdit, closeEditFileUpload, postEditComment, submitAnswerComments, closePictureUpload, closeFileUpload, picture, editToken, editPicture, editInput, editEmojiState, handleFileUpload, inputTextarea, judgeLogin, handleEditFile, selectEmoji, emojiData, emojiMaskState, emojiState, closeEmoji, openEmoji, closeAnswerCommentsChild, openAnswerCommentsChild, handleAnswerText, sendMessage, TAHomePage, operateAnswerCommentsLike, closeUserInfo, openUserInfo, permissions, commentList, commentPage, commentTotalCount, picture, userInfoWin, relatedList, relatedTime, coinNubmer, coinList, coinAmount, coinSubmit, strategy, mybalance, coinsState, openCoinBox, closeCoinBox, isLikeGif, likeClick, collectClick, islike, iscollect, recentlyList, medal, count, sectionn, tags, authorInfo, info, timestamp, updatedTime };
|
return { emojiBottomDistance, uniqidRef, share, reportToken, isReplyBoxShow, matterHeight, sidebarHeight, deleteItem, maxPicture, sidebarFixed, matterRef, sidebarRef, pitchInputState, ismyself, edit, searchInput, defaultSearchText, goSearch, goPersonalHomepage, QRcode, alsoCommentsData, copyLinkClick, reportState, tokentoken, essence, recommend, hide, report, cutShow, ismanager, show, openDiscuss, commentDelete, handleInputPaste, autoResize, editCommentState, selectEditEmoji, closeEditEmoji, openEditEmoji, closeEdit, openEdit, closeEditFileUpload, postEditComment, submitAnswerComments, closePictureUpload, closeFileUpload, picture, editToken, editPicture, editInput, editEmojiState, handleFileUpload, inputTextarea, judgeLogin, handleEditFile, selectEmoji, emojiData, emojiMaskState, emojiState, closeEmoji, openEmoji, closeAnswerCommentsChild, openAnswerCommentsChild, handleAnswerText, sendMessage, TAHomePage, operateAnswerCommentsLike, closeUserInfo, openUserInfo, permissions, commentList, commentPage, commentTotalCount, picture, userInfoWin, relatedList, relatedTime, coinNubmer, coinList, coinAmount, coinSubmit, strategy, mybalance, coinsState, openCoinBox, closeCoinBox, isLikeGif, likeClick, collectClick, islike, iscollect, recentlyList, medal, count, sectionn, tags, authorInfo, info, timestamp, updatedTime };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
317
js/edit.js
317
js/edit.js
@@ -148,11 +148,85 @@ const editApp = createApp({
|
|||||||
};
|
};
|
||||||
|
|
||||||
let editor = null;
|
let editor = null;
|
||||||
|
let toolbarRef = ref(null);
|
||||||
|
|
||||||
const initEditor = () => {
|
const initEditor = () => {
|
||||||
let infoTarget = info.value || {};
|
let infoTarget = info.value || {};
|
||||||
|
|
||||||
console.log("infoTarget", infoTarget);
|
console.log("infoTarget", infoTarget);
|
||||||
|
// 转换图片链接
|
||||||
|
async function customCheckImageFn(src, alt, url) {
|
||||||
|
// JS 语法
|
||||||
|
if (!src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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); // 文件名
|
||||||
|
|
||||||
|
await setTimeout(() => {
|
||||||
|
console.log("1111");
|
||||||
|
return true;
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
// return "图片网址必须以 http/https 开头";
|
||||||
|
// }, 2000);
|
||||||
|
if (src.indexOf("http") !== 0) {
|
||||||
|
// return "图片网址必须以 http/https 开头";
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
// 返回值有三种选择:
|
||||||
|
// 1. 返回 true ,说明检查通过,编辑器将正常插入图片
|
||||||
|
// 2. 返回一个字符串,说明检查未通过,编辑器会阻止插入。会 alert 出错误信息(即返回的字符串)
|
||||||
|
// 3. 返回 undefined(即没有任何返回),说明检查未通过,编辑器会阻止插入。但不会提示任何信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// 【新增】判断节点的对齐方式
|
||||||
|
const getNodeAlign = (node) => {
|
||||||
|
if (!node) return "left"; // 默认居左
|
||||||
|
// 获取节点的text-align样式(优先内联样式,再取CSS计算样式)
|
||||||
|
const inlineAlign = node.style.textAlign;
|
||||||
|
if (inlineAlign) return inlineAlign;
|
||||||
|
|
||||||
|
const computedStyle = window.getComputedStyle(node);
|
||||||
|
return computedStyle.textAlign || "left";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 【新增】切换对齐方式(居中 ↔ 居左)
|
||||||
|
const toggleAlign = () => {
|
||||||
|
const editorInst = editor.value;
|
||||||
|
if (!editorInst) return;
|
||||||
|
|
||||||
|
// 禁用编辑器默认的居中命令
|
||||||
|
editorInst.off("clickToolbar", "justifyCenter");
|
||||||
|
|
||||||
|
// 获取当前选中的节点(优先段落/块级节点)
|
||||||
|
const selectedNode = getSelectedNode(editorInst);
|
||||||
|
const blockNode = DomEditor.getClosestBlock(selectedNode); // 获取块级节点(p/div等)
|
||||||
|
if (!blockNode) return;
|
||||||
|
|
||||||
|
// 判断当前对齐方式
|
||||||
|
const currentAlign = getNodeAlign(blockNode);
|
||||||
|
|
||||||
|
// 切换对齐:居中 → 居左;其他 → 居中
|
||||||
|
const newAlign = currentAlign === "center" ? "left" : "center";
|
||||||
|
|
||||||
|
// 设置节点对齐样式
|
||||||
|
editorInst.restoreSelection(); // 恢复选区
|
||||||
|
blockNode.style.textAlign = newAlign;
|
||||||
|
|
||||||
|
// 触发编辑器更新
|
||||||
|
editorInst.change();
|
||||||
|
editorInst.focus(); // 保持焦点
|
||||||
|
};
|
||||||
|
|
||||||
const editorConfig = {
|
const editorConfig = {
|
||||||
placeholder: "Type here...",
|
placeholder: "Type here...",
|
||||||
@@ -162,6 +236,19 @@ const editApp = createApp({
|
|||||||
emotions: optionEmoji.value,
|
emotions: optionEmoji.value,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
["insertImage"]: {
|
||||||
|
onInsertedImage(imageNode) {
|
||||||
|
console.log("imageNode", imageNode);
|
||||||
|
// TS 语法
|
||||||
|
// onInsertedImage(imageNode) { // JS 语法
|
||||||
|
if (imageNode == null) return;
|
||||||
|
|
||||||
|
const { src, alt, url, href } = imageNode;
|
||||||
|
console.log("inserted image", src, alt, url, href);
|
||||||
|
},
|
||||||
|
// checkImage: async (src, alt, url) => await customCheckImageFn(src, alt, url), // 也支持 async 函数
|
||||||
|
},
|
||||||
|
|
||||||
["uploadImage"]: {
|
["uploadImage"]: {
|
||||||
server: uConfigData.url,
|
server: uConfigData.url,
|
||||||
|
|
||||||
@@ -200,9 +287,12 @@ const editApp = createApp({
|
|||||||
formData.append("name", file.name); // 文件名
|
formData.append("name", file.name); // 文件名
|
||||||
formData.append("type", "image"); // 文件名
|
formData.append("type", "image"); // 文件名
|
||||||
formData.append("data", config.params.data); // 文件名
|
formData.append("data", config.params.data); // 文件名
|
||||||
|
// uploading(file, file.name, "image").then((data) => {
|
||||||
|
// insertFn(data.url); // 传入图片的可访问 URL
|
||||||
|
// });
|
||||||
ajax(config.url, formData).then((res) => {
|
ajax(config.url, formData).then((res) => {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
|
console.log("上传成功:", data);
|
||||||
insertFn(data.url); // 传入图片的可访问 URL
|
insertFn(data.url); // 传入图片的可访问 URL
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -210,23 +300,76 @@ const editApp = createApp({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
// 4. 链接菜单:显式启用(默认启用,补充配置防止被过滤)
|
["uploadVideo"]: {
|
||||||
link: {
|
server: uConfigData.url,
|
||||||
disabled: false, // 确保不禁用
|
|
||||||
showTarget: true, // 显示「是否新窗口打开」选项
|
// form-data fieldName ,默认值 'wangeditor-uploaded-video'
|
||||||
showRel: true, // 显示「rel 属性」选项
|
fieldName: uConfigData.requestName,
|
||||||
},
|
|
||||||
// 5. 对齐菜单:显式启用(默认启用,兜底配置)
|
// 单个文件的最大体积限制,默认为 10M
|
||||||
justify: {
|
maxFileSize: maxSize, // 1M
|
||||||
disabled: false,
|
|
||||||
|
// 最多可上传几个文件,默认为 5
|
||||||
|
maxNumberOfFiles: videoLength,
|
||||||
|
|
||||||
|
// 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
|
||||||
|
allowedFileTypes: ["video/*"],
|
||||||
|
|
||||||
|
// 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
|
||||||
|
meta: { ...uConfigData.params },
|
||||||
|
|
||||||
|
// 将 meta 拼接到 url 参数中,默认 false
|
||||||
|
metaWithUrl: false,
|
||||||
|
|
||||||
|
// 自定义增加 http header
|
||||||
|
headers: { accept: "application/json, text/plain, */*", ...uConfigData.headers },
|
||||||
|
|
||||||
|
// 跨域是否传递 cookie ,默认为 false
|
||||||
|
withCredentials: true,
|
||||||
|
|
||||||
|
// 超时时间,默认为 30 秒
|
||||||
|
timeout: 15 * 1000, // 15 秒
|
||||||
|
|
||||||
|
// 视频不支持 base64 格式插入
|
||||||
|
|
||||||
|
async customUpload(file, insertFn) {
|
||||||
|
try {
|
||||||
|
const videoUploadRes = await uploading(file, file.name, "video");
|
||||||
|
|
||||||
|
const coverFile = await getVideoFirstFrame(file);
|
||||||
|
console.log("第一帧提取成功", coverFile);
|
||||||
|
|
||||||
|
// 步骤3:再上传第一帧封面(type 传 'cover',按后端要求调整)
|
||||||
|
const coverUploadRes = await uploading(coverFile, coverFile.name, "image");
|
||||||
|
console.log("封面上传成功", coverUploadRes);
|
||||||
|
|
||||||
|
insertFn(videoUploadRes.url, coverUploadRes.url);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("上传出错:", err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
["justifyCenter"]: {
|
||||||
|
onClick: (editor) => {
|
||||||
|
console.log("editor", editor);
|
||||||
|
toggleAlign(); // 替换为自定义切换逻辑
|
||||||
|
},
|
||||||
|
// 【可选】自定义居中按钮的激活状态(选中时高亮)
|
||||||
|
isActive: (editor) => {
|
||||||
|
const selectedNode = getSelectedNode(editor);
|
||||||
|
const blockNode = DomEditor.getClosestBlock(selectedNode);
|
||||||
|
return blockNode && getNodeAlign(blockNode) === "center";
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange(editor) {
|
onChange(editor) {
|
||||||
const html = editor.getHtml();
|
const html = editor.getHtml();
|
||||||
|
// console.log('"editor', editor);
|
||||||
console.log("editor content", html);
|
console.log("editor content", html);
|
||||||
// 也可以同步到 <textarea>
|
updateWHeadingStatus();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -237,32 +380,31 @@ const editApp = createApp({
|
|||||||
mode: "default",
|
mode: "default",
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log("editor", editor);
|
|
||||||
editor.addMark("bold", true); // 加粗
|
|
||||||
}, 1000);
|
|
||||||
// const toolbar = DomEditor.getToolbar(editor)
|
// const toolbar = DomEditor.getToolbar(editor)
|
||||||
|
|
||||||
const toolbarConfig = {
|
const toolbarConfig = {
|
||||||
// toolbarKeys: ["bold", "italic", "list"],
|
// toolbarKeys: ["bold", "italic", "list"],
|
||||||
toolbarKeys: [
|
toolbarKeys: [
|
||||||
"headerSelect", // 标题
|
"header2", // 标题
|
||||||
"bold", // 粗体
|
|
||||||
"italic", // 斜体
|
|
||||||
// "justify", // 对齐方式
|
|
||||||
{
|
{
|
||||||
key: "justifyCenter",
|
key: "group-image",
|
||||||
title: "对齐",
|
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: ["insertImage", "uploadImage"],
|
||||||
menuKeys: ["justifyLeft", "justifyRight", "justifyCenter", "justifyJustify"],
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "group-video",
|
||||||
|
title: "视频",
|
||||||
|
menuKeys: ["insertVideo", "uploadVideo"],
|
||||||
|
},
|
||||||
|
// "insertVideo",
|
||||||
|
|
||||||
"emotion", // 表情
|
"emotion", // 表情
|
||||||
|
|
||||||
|
// "uploadImage", // 插入图片
|
||||||
|
// "uploadVideo", // 插入视频
|
||||||
"insertLink", // 插入链接
|
"insertLink", // 插入链接
|
||||||
"uploadImage", // 插入图片
|
"bold", // 粗体
|
||||||
"uploadVideo", // 插入视频
|
"justifyCenter",
|
||||||
"undo", // 撤销
|
|
||||||
"redo", // 重做
|
|
||||||
"fullScreen", // 全屏
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -272,15 +414,44 @@ const editApp = createApp({
|
|||||||
config: toolbarConfig,
|
config: toolbarConfig,
|
||||||
mode: "default",
|
mode: "default",
|
||||||
});
|
});
|
||||||
|
console.log("editor.commands", editor);
|
||||||
|
|
||||||
console.log("toolbar", toolbar);
|
nextTick(() => {
|
||||||
|
const h2 = toolbarRef.value.querySelector('[data-menu-key="header2"]');
|
||||||
|
const h2Item = h2.parentElement;
|
||||||
|
h2Item.classList.add("toolbar-item", "flexacenter");
|
||||||
|
h2.innerHTML = '<img class="icon" src="{@/img/t-icon.png}" alt="段落标题" /> <span>段落标题</span>';
|
||||||
|
|
||||||
// setTimeout(() => {
|
const image = toolbarRef.value.querySelector('[data-menu-key="group-image"]');
|
||||||
// const el = document.querySelector("#toolbar-container");
|
const imageItem = image.parentElement;
|
||||||
// if (el && el.children.length === 0) {
|
imageItem.classList.add("toolbar-item", "flexacenter");
|
||||||
// createToolbar({ editor, selector: "#toolbar-container", config: toolbarConfig, mode: "default" });
|
image.innerHTML = '<img class="icon" src="{@/img/img-icon.png}" alt="图片" /> <span>图片</span>';
|
||||||
// }
|
|
||||||
// }, 0);
|
const video = toolbarRef.value.querySelector('[data-menu-key="group-video"]');
|
||||||
|
const videoItem = video.parentElement;
|
||||||
|
videoItem.classList.add("toolbar-item", "flexacenter");
|
||||||
|
video.innerHTML = '<img class="icon" src="{@/img/video-icon.png}" alt="视频" /> <span>视频</span>';
|
||||||
|
|
||||||
|
const emotion = toolbarRef.value.querySelector('[data-menu-key="emotion"]');
|
||||||
|
const emotionItem = emotion.parentElement;
|
||||||
|
emotionItem.classList.add("toolbar-item", "flexacenter");
|
||||||
|
emotion.innerHTML = '<img class="icon" src="{@/img/emotion-icon.png}" alt="表情" /> <span>表情</span>';
|
||||||
|
|
||||||
|
const link = toolbarRef.value.querySelector('[data-menu-key="insertLink"]');
|
||||||
|
const linkItem = link.parentElement;
|
||||||
|
linkItem.classList.add("toolbar-item", "flexacenter");
|
||||||
|
link.innerHTML = '<img class="icon" src="{@/img/link-icon.png}" alt="链接" /> <span>链接</span>';
|
||||||
|
|
||||||
|
const bold = toolbarRef.value.querySelector('[data-menu-key="bold"]');
|
||||||
|
const boldItem = bold.parentElement;
|
||||||
|
boldItem.classList.add("toolbar-item", "flexacenter");
|
||||||
|
bold.innerHTML = '<img class="icon" src="{@/img/bold-icon.png}" alt="粗体" /> <span>粗体</span>';
|
||||||
|
|
||||||
|
const justifyCenter = toolbarRef.value.querySelector('[data-menu-key="justifyCenter"]');
|
||||||
|
const justifyCenterItem = justifyCenter.parentElement;
|
||||||
|
justifyCenterItem.classList.add("toolbar-item", "flexacenter");
|
||||||
|
justifyCenter.innerHTML = '<img class="icon" src="{@/img/justify-center-icon.png}" alt="居中" /> <span>居中</span>';
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const restoreHtml = (formattedText, attachments) => {
|
const restoreHtml = (formattedText, attachments) => {
|
||||||
@@ -370,6 +541,35 @@ const editApp = createApp({
|
|||||||
};
|
};
|
||||||
|
|
||||||
let lastSelection = null;
|
let lastSelection = null;
|
||||||
|
let lastSelectionW = null;
|
||||||
|
const isH1 = ref(false);
|
||||||
|
const updateWHeadingStatus = () => {
|
||||||
|
const wRoot = document.querySelector("#editor-container");
|
||||||
|
let node = null;
|
||||||
|
try {
|
||||||
|
const DomEditor = window.wangEditor && window.wangEditor.DomEditor;
|
||||||
|
if (DomEditor && editor) node = DomEditor.getSelectionNode(editor);
|
||||||
|
} catch (e) {}
|
||||||
|
if (!node) {
|
||||||
|
const sel = window.getSelection();
|
||||||
|
if (sel && sel.rangeCount) node = sel.getRangeAt(0).commonAncestorContainer;
|
||||||
|
}
|
||||||
|
let el = node && node.nodeType === 3 ? node.parentElement : node;
|
||||||
|
|
||||||
|
while (el && el !== wRoot && el && el.nodeType === 1) {
|
||||||
|
if (window.getComputedStyle(el).getPropertyValue("text-align") === "center") {
|
||||||
|
console.log("居中");
|
||||||
|
const justifyCenter = toolbarRef.value.querySelector('[data-menu-key="justifyCenter"]');
|
||||||
|
if (justifyCenter) {
|
||||||
|
const justifyCenterItem = justifyCenter.parentElement;
|
||||||
|
|
||||||
|
justifyCenterItem.classList.add("active");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
el = el.parentElement;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let loading = ref(false);
|
let loading = ref(false);
|
||||||
|
|
||||||
@@ -553,36 +753,41 @@ const editApp = createApp({
|
|||||||
const handleSelectionChange = () => {
|
const handleSelectionChange = () => {
|
||||||
return;
|
return;
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
// 确保有选中内容且选中区域在编辑器内
|
|
||||||
if (selection.rangeCount > 0) {
|
if (selection.rangeCount > 0) {
|
||||||
const range = selection.getRangeAt(0);
|
const range = selection.getRangeAt(0);
|
||||||
// 检查选中区域是否在编辑器内
|
|
||||||
const commonAncestor = range.commonAncestorContainer;
|
const commonAncestor = range.commonAncestorContainer;
|
||||||
if (editorRef.value.contains(commonAncestor)) {
|
if (editorRef.value.contains(commonAncestor)) {
|
||||||
console.log("选中区域在编辑器内", range);
|
|
||||||
lastSelection = range;
|
lastSelection = range;
|
||||||
}
|
}
|
||||||
|
const wRoot = document.querySelector("#editor-container");
|
||||||
|
if (wRoot && wRoot.contains(commonAncestor)) {
|
||||||
|
lastSelectionW = range;
|
||||||
|
updateWHeadingStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isPTitle = ref(false);
|
let isPTitle = ref(false);
|
||||||
|
|
||||||
const paragraphTitle = () => {
|
const paragraphTitle = () => {
|
||||||
editorRef.value.focus();
|
console.log("editor", editor.addMark);
|
||||||
if (!lastSelection) return;
|
// editor.addMark("bold", true); // 加粗
|
||||||
const selection = window.getSelection();
|
|
||||||
selection.removeAllRanges();
|
|
||||||
selection.addRange(lastSelection);
|
|
||||||
|
|
||||||
// 使用try-catch确保即使命令执行失败也能恢复滚动位置
|
// editorRef.value.focus();
|
||||||
try {
|
// if (!lastSelection) return;
|
||||||
document.execCommand("formatBlock", false, isPTitle.value ? "P" : "H2");
|
// const selection = window.getSelection();
|
||||||
} catch (error) {
|
// selection.removeAllRanges();
|
||||||
console.error("应用段落格式失败:", error);
|
// selection.addRange(lastSelection);
|
||||||
}
|
|
||||||
|
|
||||||
// 更新状态
|
// // 使用try-catch确保即使命令执行失败也能恢复滚动位置
|
||||||
setTimeout(() => updatePTitleStatus(), 100);
|
// try {
|
||||||
|
// document.execCommand("formatBlock", false, isPTitle.value ? "P" : "H2");
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("应用段落格式失败:", error);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 更新状态
|
||||||
|
// setTimeout(() => updatePTitleStatus(), 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updatePTitleStatus = () => {
|
const updatePTitleStatus = () => {
|
||||||
@@ -656,6 +861,8 @@ const editApp = createApp({
|
|||||||
content = formatContent(content);
|
content = formatContent(content);
|
||||||
console.log(content);
|
console.log(content);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
...infoTarget,
|
...infoTarget,
|
||||||
content,
|
content,
|
||||||
@@ -893,11 +1100,11 @@ const editApp = createApp({
|
|||||||
console.log("加粗");
|
console.log("加粗");
|
||||||
|
|
||||||
editor.addMark("bold", true); // 加粗
|
editor.addMark("bold", true); // 加粗
|
||||||
editor.addMark("color", "#999"); // 文本颜色
|
// editor.addMark("color", "#999"); // 文本颜色
|
||||||
console.log("editor", editor.addMark);
|
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 };
|
return { toolbarRef, overstriking, isH1, 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 };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
16
js/public.js
16
js/public.js
@@ -2,6 +2,8 @@ const forumBaseURL = "https://api.gter.net";
|
|||||||
axios.defaults.withCredentials = true;
|
axios.defaults.withCredentials = true;
|
||||||
axios.defaults.emulateJSON = true;
|
axios.defaults.emulateJSON = true;
|
||||||
|
|
||||||
|
const withVer = (p) => `${p}?v=${window.__ASSET_VERSION__}`;
|
||||||
|
|
||||||
// 导出ajax函数
|
// 导出ajax函数
|
||||||
const ajax = (url, data) => {
|
const ajax = (url, data) => {
|
||||||
axios.defaults.withCredentials = true;
|
axios.defaults.withCredentials = true;
|
||||||
@@ -402,3 +404,17 @@ const go_ajax_Login = () => {
|
|||||||
if (typeof ajax_login === "function") ajax_login();
|
if (typeof ajax_login === "function") ajax_login();
|
||||||
else window.open("https://passport.gter.net/?referer=" + escape(location.href), "_self");
|
else window.open("https://passport.gter.net/?referer=" + escape(location.href), "_self");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const loadJsFile = (url) => {
|
||||||
|
// var xhr = new XMLHttpRequest();
|
||||||
|
// xhr.open("GET", url, true);
|
||||||
|
// xhr.onreadystatechange = function () {
|
||||||
|
// if (xhr.readyState === 4 && xhr.status === 200) {
|
||||||
|
// var scriptCode = xhr.responseText;
|
||||||
|
// var script = document.createElement("script");
|
||||||
|
// script.innerHTML = scriptCode;
|
||||||
|
// document.head.appendChild(script);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// xhr.send();
|
||||||
|
// };
|
||||||
|
|||||||
Reference in New Issue
Block a user